@animus-labs/cortex 0.2.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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/budget-guard.d.ts +75 -0
- package/dist/budget-guard.d.ts.map +1 -0
- package/dist/budget-guard.js +142 -0
- package/dist/budget-guard.js.map +1 -0
- package/dist/compaction/compaction.d.ts +99 -0
- package/dist/compaction/compaction.d.ts.map +1 -0
- package/dist/compaction/compaction.js +302 -0
- package/dist/compaction/compaction.js.map +1 -0
- package/dist/compaction/failsafe.d.ts +57 -0
- package/dist/compaction/failsafe.d.ts.map +1 -0
- package/dist/compaction/failsafe.js +135 -0
- package/dist/compaction/failsafe.js.map +1 -0
- package/dist/compaction/index.d.ts +381 -0
- package/dist/compaction/index.d.ts.map +1 -0
- package/dist/compaction/index.js +979 -0
- package/dist/compaction/index.js.map +1 -0
- package/dist/compaction/microcompaction.d.ts +219 -0
- package/dist/compaction/microcompaction.d.ts.map +1 -0
- package/dist/compaction/microcompaction.js +536 -0
- package/dist/compaction/microcompaction.js.map +1 -0
- package/dist/compaction/observational/buffering.d.ts +225 -0
- package/dist/compaction/observational/buffering.d.ts.map +1 -0
- package/dist/compaction/observational/buffering.js +354 -0
- package/dist/compaction/observational/buffering.js.map +1 -0
- package/dist/compaction/observational/constants.d.ts +70 -0
- package/dist/compaction/observational/constants.d.ts.map +1 -0
- package/dist/compaction/observational/constants.js +507 -0
- package/dist/compaction/observational/constants.js.map +1 -0
- package/dist/compaction/observational/index.d.ts +219 -0
- package/dist/compaction/observational/index.d.ts.map +1 -0
- package/dist/compaction/observational/index.js +641 -0
- package/dist/compaction/observational/index.js.map +1 -0
- package/dist/compaction/observational/observer.d.ts +97 -0
- package/dist/compaction/observational/observer.d.ts.map +1 -0
- package/dist/compaction/observational/observer.js +424 -0
- package/dist/compaction/observational/observer.js.map +1 -0
- package/dist/compaction/observational/recall-tool.d.ts +27 -0
- package/dist/compaction/observational/recall-tool.d.ts.map +1 -0
- package/dist/compaction/observational/recall-tool.js +93 -0
- package/dist/compaction/observational/recall-tool.js.map +1 -0
- package/dist/compaction/observational/reflector.d.ts +94 -0
- package/dist/compaction/observational/reflector.d.ts.map +1 -0
- package/dist/compaction/observational/reflector.js +167 -0
- package/dist/compaction/observational/reflector.js.map +1 -0
- package/dist/compaction/observational/types.d.ts +271 -0
- package/dist/compaction/observational/types.d.ts.map +1 -0
- package/dist/compaction/observational/types.js +15 -0
- package/dist/compaction/observational/types.js.map +1 -0
- package/dist/context-manager.d.ts +134 -0
- package/dist/context-manager.d.ts.map +1 -0
- package/dist/context-manager.js +170 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/cortex-agent.d.ts +1020 -0
- package/dist/cortex-agent.d.ts.map +1 -0
- package/dist/cortex-agent.js +3589 -0
- package/dist/cortex-agent.js.map +1 -0
- package/dist/error-classifier.d.ts +48 -0
- package/dist/error-classifier.d.ts.map +1 -0
- package/dist/error-classifier.js +152 -0
- package/dist/error-classifier.js.map +1 -0
- package/dist/event-bridge.d.ts +166 -0
- package/dist/event-bridge.d.ts.map +1 -0
- package/dist/event-bridge.js +381 -0
- package/dist/event-bridge.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-client.d.ts +119 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +474 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/model-wrapper.d.ts +58 -0
- package/dist/model-wrapper.d.ts.map +1 -0
- package/dist/model-wrapper.js +86 -0
- package/dist/model-wrapper.js.map +1 -0
- package/dist/noop-logger.d.ts +4 -0
- package/dist/noop-logger.d.ts.map +1 -0
- package/dist/noop-logger.js +8 -0
- package/dist/noop-logger.js.map +1 -0
- package/dist/prompt-diagnostics.d.ts +47 -0
- package/dist/prompt-diagnostics.d.ts.map +1 -0
- package/dist/prompt-diagnostics.js +230 -0
- package/dist/prompt-diagnostics.js.map +1 -0
- package/dist/provider-manager.d.ts +224 -0
- package/dist/provider-manager.d.ts.map +1 -0
- package/dist/provider-manager.js +563 -0
- package/dist/provider-manager.js.map +1 -0
- package/dist/provider-registry.d.ts +115 -0
- package/dist/provider-registry.d.ts.map +1 -0
- package/dist/provider-registry.js +305 -0
- package/dist/provider-registry.js.map +1 -0
- package/dist/schema-converter.d.ts +20 -0
- package/dist/schema-converter.d.ts.map +1 -0
- package/dist/schema-converter.js +48 -0
- package/dist/schema-converter.js.map +1 -0
- package/dist/skill-preprocessor.d.ts +46 -0
- package/dist/skill-preprocessor.d.ts.map +1 -0
- package/dist/skill-preprocessor.js +237 -0
- package/dist/skill-preprocessor.js.map +1 -0
- package/dist/skill-registry.d.ts +107 -0
- package/dist/skill-registry.d.ts.map +1 -0
- package/dist/skill-registry.js +330 -0
- package/dist/skill-registry.js.map +1 -0
- package/dist/skill-tool.d.ts +54 -0
- package/dist/skill-tool.d.ts.map +1 -0
- package/dist/skill-tool.js +88 -0
- package/dist/skill-tool.js.map +1 -0
- package/dist/sub-agent-manager.d.ts +90 -0
- package/dist/sub-agent-manager.d.ts.map +1 -0
- package/dist/sub-agent-manager.js +192 -0
- package/dist/sub-agent-manager.js.map +1 -0
- package/dist/token-estimator.d.ts +23 -0
- package/dist/token-estimator.d.ts.map +1 -0
- package/dist/token-estimator.js +27 -0
- package/dist/token-estimator.js.map +1 -0
- package/dist/tool-contract.d.ts +68 -0
- package/dist/tool-contract.d.ts.map +1 -0
- package/dist/tool-contract.js +35 -0
- package/dist/tool-contract.js.map +1 -0
- package/dist/tool-result-persistence.d.ts +89 -0
- package/dist/tool-result-persistence.d.ts.map +1 -0
- package/dist/tool-result-persistence.js +152 -0
- package/dist/tool-result-persistence.js.map +1 -0
- package/dist/tools/bash/index.d.ts +71 -0
- package/dist/tools/bash/index.d.ts.map +1 -0
- package/dist/tools/bash/index.js +485 -0
- package/dist/tools/bash/index.js.map +1 -0
- package/dist/tools/bash/interactive.d.ts +47 -0
- package/dist/tools/bash/interactive.d.ts.map +1 -0
- package/dist/tools/bash/interactive.js +262 -0
- package/dist/tools/bash/interactive.js.map +1 -0
- package/dist/tools/bash/safety.d.ts +149 -0
- package/dist/tools/bash/safety.d.ts.map +1 -0
- package/dist/tools/bash/safety.js +1116 -0
- package/dist/tools/bash/safety.js.map +1 -0
- package/dist/tools/edit.d.ts +57 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +310 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +34 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +268 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +53 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +673 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +62 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +52 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.d.ts +43 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +459 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/runtime.d.ts +62 -0
- package/dist/tools/runtime.d.ts.map +1 -0
- package/dist/tools/runtime.js +116 -0
- package/dist/tools/runtime.js.map +1 -0
- package/dist/tools/shared/cwd-tracker.d.ts +32 -0
- package/dist/tools/shared/cwd-tracker.d.ts.map +1 -0
- package/dist/tools/shared/cwd-tracker.js +44 -0
- package/dist/tools/shared/cwd-tracker.js.map +1 -0
- package/dist/tools/shared/edit-history.d.ts +55 -0
- package/dist/tools/shared/edit-history.d.ts.map +1 -0
- package/dist/tools/shared/edit-history.js +72 -0
- package/dist/tools/shared/edit-history.js.map +1 -0
- package/dist/tools/shared/edit-matcher.d.ts +83 -0
- package/dist/tools/shared/edit-matcher.d.ts.map +1 -0
- package/dist/tools/shared/edit-matcher.js +359 -0
- package/dist/tools/shared/edit-matcher.js.map +1 -0
- package/dist/tools/shared/file-mutation-lock.d.ts +22 -0
- package/dist/tools/shared/file-mutation-lock.d.ts.map +1 -0
- package/dist/tools/shared/file-mutation-lock.js +35 -0
- package/dist/tools/shared/file-mutation-lock.js.map +1 -0
- package/dist/tools/shared/gitignore.d.ts +17 -0
- package/dist/tools/shared/gitignore.d.ts.map +1 -0
- package/dist/tools/shared/gitignore.js +59 -0
- package/dist/tools/shared/gitignore.js.map +1 -0
- package/dist/tools/shared/pdf-extractor.d.ts +96 -0
- package/dist/tools/shared/pdf-extractor.d.ts.map +1 -0
- package/dist/tools/shared/pdf-extractor.js +196 -0
- package/dist/tools/shared/pdf-extractor.js.map +1 -0
- package/dist/tools/shared/read-registry.d.ts +66 -0
- package/dist/tools/shared/read-registry.d.ts.map +1 -0
- package/dist/tools/shared/read-registry.js +65 -0
- package/dist/tools/shared/read-registry.js.map +1 -0
- package/dist/tools/shared/safe-env.d.ts +18 -0
- package/dist/tools/shared/safe-env.d.ts.map +1 -0
- package/dist/tools/shared/safe-env.js +70 -0
- package/dist/tools/shared/safe-env.js.map +1 -0
- package/dist/tools/sub-agent.d.ts +91 -0
- package/dist/tools/sub-agent.d.ts.map +1 -0
- package/dist/tools/sub-agent.js +89 -0
- package/dist/tools/sub-agent.js.map +1 -0
- package/dist/tools/task-output.d.ts +38 -0
- package/dist/tools/task-output.d.ts.map +1 -0
- package/dist/tools/task-output.js +186 -0
- package/dist/tools/task-output.js.map +1 -0
- package/dist/tools/tool-search/index.d.ts +40 -0
- package/dist/tools/tool-search/index.d.ts.map +1 -0
- package/dist/tools/tool-search/index.js +110 -0
- package/dist/tools/tool-search/index.js.map +1 -0
- package/dist/tools/tool-search/registry.d.ts +82 -0
- package/dist/tools/tool-search/registry.d.ts.map +1 -0
- package/dist/tools/tool-search/registry.js +238 -0
- package/dist/tools/tool-search/registry.js.map +1 -0
- package/dist/tools/undo-edit.d.ts +51 -0
- package/dist/tools/undo-edit.d.ts.map +1 -0
- package/dist/tools/undo-edit.js +231 -0
- package/dist/tools/undo-edit.js.map +1 -0
- package/dist/tools/web-fetch/cache.d.ts +49 -0
- package/dist/tools/web-fetch/cache.d.ts.map +1 -0
- package/dist/tools/web-fetch/cache.js +89 -0
- package/dist/tools/web-fetch/cache.js.map +1 -0
- package/dist/tools/web-fetch/index.d.ts +53 -0
- package/dist/tools/web-fetch/index.d.ts.map +1 -0
- package/dist/tools/web-fetch/index.js +513 -0
- package/dist/tools/web-fetch/index.js.map +1 -0
- package/dist/tools/write.d.ts +59 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +316 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +881 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/working-tags.d.ts +44 -0
- package/dist/working-tags.d.ts.map +1 -0
- package/dist/working-tags.js +103 -0
- package/dist/working-tags.js.map +1 -0
- package/package.json +87 -0
- package/src/budget-guard.ts +170 -0
- package/src/compaction/compaction.ts +386 -0
- package/src/compaction/failsafe.ts +185 -0
- package/src/compaction/index.ts +1199 -0
- package/src/compaction/microcompaction.ts +709 -0
- package/src/compaction/observational/buffering.ts +430 -0
- package/src/compaction/observational/constants.ts +532 -0
- package/src/compaction/observational/index.ts +837 -0
- package/src/compaction/observational/observer.ts +510 -0
- package/src/compaction/observational/recall-tool.ts +130 -0
- package/src/compaction/observational/reflector.ts +221 -0
- package/src/compaction/observational/types.ts +343 -0
- package/src/context-manager.ts +237 -0
- package/src/cortex-agent.ts +4297 -0
- package/src/error-classifier.ts +199 -0
- package/src/event-bridge.ts +508 -0
- package/src/index.ts +292 -0
- package/src/mcp-client.ts +582 -0
- package/src/model-wrapper.ts +128 -0
- package/src/noop-logger.ts +9 -0
- package/src/prompt-diagnostics.ts +296 -0
- package/src/provider-manager.ts +823 -0
- package/src/provider-registry.ts +386 -0
- package/src/schema-converter.ts +51 -0
- package/src/skill-preprocessor.ts +314 -0
- package/src/skill-registry.ts +378 -0
- package/src/skill-tool.ts +130 -0
- package/src/sub-agent-manager.ts +236 -0
- package/src/token-estimator.ts +26 -0
- package/src/tool-contract.ts +113 -0
- package/src/tool-result-persistence.ts +197 -0
- package/src/tools/bash/index.ts +633 -0
- package/src/tools/bash/interactive.ts +302 -0
- package/src/tools/bash/safety.ts +1297 -0
- package/src/tools/edit.ts +422 -0
- package/src/tools/glob.ts +330 -0
- package/src/tools/grep.ts +819 -0
- package/src/tools/index.ts +110 -0
- package/src/tools/read.ts +580 -0
- package/src/tools/runtime.ts +173 -0
- package/src/tools/shared/cwd-tracker.ts +50 -0
- package/src/tools/shared/edit-history.ts +96 -0
- package/src/tools/shared/edit-matcher.ts +457 -0
- package/src/tools/shared/file-mutation-lock.ts +40 -0
- package/src/tools/shared/gitignore.ts +61 -0
- package/src/tools/shared/pdf-extractor.ts +290 -0
- package/src/tools/shared/read-registry.ts +93 -0
- package/src/tools/shared/safe-env.ts +82 -0
- package/src/tools/sub-agent.ts +171 -0
- package/src/tools/task-output.ts +236 -0
- package/src/tools/tool-search/index.ts +167 -0
- package/src/tools/tool-search/registry.ts +278 -0
- package/src/tools/undo-edit.ts +314 -0
- package/src/tools/web-fetch/cache.ts +112 -0
- package/src/tools/web-fetch/index.ts +604 -0
- package/src/tools/write.ts +385 -0
- package/src/types.ts +1057 -0
- package/src/working-tags.ts +118 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflector module for the observational memory system.
|
|
3
|
+
*
|
|
4
|
+
* The Reflector condenses observations when they grow too large. It runs
|
|
5
|
+
* on the utility model and uses progressive compression: starting with
|
|
6
|
+
* no compression guidance (level 0) and escalating through levels 1-4
|
|
7
|
+
* if the output exceeds the target token threshold.
|
|
8
|
+
*
|
|
9
|
+
* References:
|
|
10
|
+
* - observational-memory-architecture.md (Reflector System section)
|
|
11
|
+
* - compaction-strategy.md
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { CompleteFn } from '../compaction.js';
|
|
15
|
+
import type { ReflectorOutput } from './types.js';
|
|
16
|
+
import {
|
|
17
|
+
REFLECTOR_SYSTEM_PROMPT,
|
|
18
|
+
COMPRESSION_LEVEL_GUIDANCE,
|
|
19
|
+
} from './constants.js';
|
|
20
|
+
import { estimateTokens } from '../../token-estimator.js';
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Prompt Building
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build the full reflector system prompt.
|
|
28
|
+
*
|
|
29
|
+
* Starts with the base reflector prompt, then appends compression level
|
|
30
|
+
* guidance and optional consumer instructions.
|
|
31
|
+
*
|
|
32
|
+
* @param compressionLevel - Compression level (0-4). Level 0 adds no
|
|
33
|
+
* compression guidance.
|
|
34
|
+
* @param customInstruction - Optional consumer-provided instruction to
|
|
35
|
+
* append to the prompt.
|
|
36
|
+
* @returns The assembled system prompt string.
|
|
37
|
+
*/
|
|
38
|
+
export function buildReflectorPrompt(
|
|
39
|
+
compressionLevel: number,
|
|
40
|
+
customInstruction?: string,
|
|
41
|
+
): string {
|
|
42
|
+
let prompt = REFLECTOR_SYSTEM_PROMPT;
|
|
43
|
+
|
|
44
|
+
const guidance = COMPRESSION_LEVEL_GUIDANCE[compressionLevel];
|
|
45
|
+
if (compressionLevel > 0 && guidance) {
|
|
46
|
+
prompt += `\n\n## Compression Target\n\n${guidance}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (customInstruction) {
|
|
50
|
+
prompt += `\n\n## Additional Instructions\n\n${customInstruction}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return prompt;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Message Building
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Build the message array to send to the reflector LLM.
|
|
62
|
+
*
|
|
63
|
+
* Creates two user messages: one containing the observations to reflect on,
|
|
64
|
+
* and one with the output instruction.
|
|
65
|
+
*
|
|
66
|
+
* @param observations - The full observation text to consolidate.
|
|
67
|
+
* @returns An array of message objects for the LLM call.
|
|
68
|
+
*/
|
|
69
|
+
export function buildReflectorMessages(
|
|
70
|
+
observations: string,
|
|
71
|
+
): unknown[] {
|
|
72
|
+
return [
|
|
73
|
+
{
|
|
74
|
+
role: 'user',
|
|
75
|
+
content:
|
|
76
|
+
'Here are all current observations to reflect on and consolidate:\n\n' +
|
|
77
|
+
observations,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
role: 'user',
|
|
81
|
+
content:
|
|
82
|
+
'Produce your consolidated reflections. Follow the observation format exactly. Output ONLY the consolidated observations, nothing else.',
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Output Parsing
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse the raw LLM output from the reflector.
|
|
93
|
+
*
|
|
94
|
+
* Extracts content from `<observations>` tags if present, strips any
|
|
95
|
+
* analysis/thinking tags, and trims whitespace.
|
|
96
|
+
*
|
|
97
|
+
* @param raw - The raw string output from the reflector LLM call.
|
|
98
|
+
* @returns The cleaned observation text.
|
|
99
|
+
*/
|
|
100
|
+
export function parseReflectorOutput(raw: string): string {
|
|
101
|
+
let output = raw;
|
|
102
|
+
|
|
103
|
+
// Strip analysis/thinking tags if present
|
|
104
|
+
output = output.replace(/<analysis>[\s\S]*?<\/analysis>/g, '');
|
|
105
|
+
output = output.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
|
|
106
|
+
|
|
107
|
+
// Extract content from <observations> tags if present
|
|
108
|
+
const match = /<observations>([\s\S]*?)<\/observations>/.exec(output);
|
|
109
|
+
if (match?.[1]) {
|
|
110
|
+
output = match[1];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return output.trim();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Validation
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Check whether the reflector output is within the target token budget.
|
|
122
|
+
*
|
|
123
|
+
* @param output - The parsed reflector output text.
|
|
124
|
+
* @param targetTokens - The maximum allowed token count.
|
|
125
|
+
* @returns `true` if estimated tokens are at or below the target.
|
|
126
|
+
*/
|
|
127
|
+
export function validateCompression(
|
|
128
|
+
output: string,
|
|
129
|
+
targetTokens: number,
|
|
130
|
+
): boolean {
|
|
131
|
+
return estimateTokens(output) <= targetTokens;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Threshold Computation
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Compute the effective reflection threshold by clamping to both the
|
|
140
|
+
* primary model's context window and the utility model's context window.
|
|
141
|
+
*
|
|
142
|
+
* The threshold is the smaller of:
|
|
143
|
+
* - `reflectionThreshold` as a percentage of the primary context window
|
|
144
|
+
* - 50% of the utility model's context window (to ensure the reflector
|
|
145
|
+
* input fits within the utility model)
|
|
146
|
+
*
|
|
147
|
+
* @param contextWindow - The primary model's context window size in tokens.
|
|
148
|
+
* @param reflectionThreshold - Fraction of the context window (e.g. 0.20).
|
|
149
|
+
* @param utilityModelContextWindow - The utility model's context window
|
|
150
|
+
* size in tokens.
|
|
151
|
+
* @returns The effective reflection threshold in tokens.
|
|
152
|
+
*/
|
|
153
|
+
export function computeEffectiveReflectionThreshold(
|
|
154
|
+
contextWindow: number,
|
|
155
|
+
reflectionThreshold: number,
|
|
156
|
+
utilityModelContextWindow: number,
|
|
157
|
+
): number {
|
|
158
|
+
return Math.min(
|
|
159
|
+
contextWindow * reflectionThreshold,
|
|
160
|
+
utilityModelContextWindow * 0.5,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// Reflector Execution
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
const MAX_RETRIES = 4;
|
|
169
|
+
const MAX_COMPRESSION_LEVEL = 4;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Run the reflector with progressive compression retry.
|
|
173
|
+
*
|
|
174
|
+
* Starts at compression level 0 and escalates if the output exceeds the
|
|
175
|
+
* reflection threshold. Retries up to 3 times, incrementing the
|
|
176
|
+
* compression level each time (capped at level 4).
|
|
177
|
+
*
|
|
178
|
+
* Even if the final attempt does not validate, the best result is returned.
|
|
179
|
+
* The observation slot will be larger than ideal, but the next reflection
|
|
180
|
+
* cycle will try again.
|
|
181
|
+
*
|
|
182
|
+
* @param complete - The LLM completion function.
|
|
183
|
+
* @param observations - The full observation text to consolidate.
|
|
184
|
+
* @param config - Configuration with reflectionThreshold (in tokens) and
|
|
185
|
+
* optional reflectorInstruction.
|
|
186
|
+
* @returns The reflector output with consolidated observations and the
|
|
187
|
+
* compression level that was applied.
|
|
188
|
+
*/
|
|
189
|
+
export async function runReflector(
|
|
190
|
+
complete: CompleteFn,
|
|
191
|
+
observations: string,
|
|
192
|
+
config: {
|
|
193
|
+
reflectionThreshold: number;
|
|
194
|
+
reflectorInstruction?: string;
|
|
195
|
+
},
|
|
196
|
+
): Promise<ReflectorOutput> {
|
|
197
|
+
let level = 0;
|
|
198
|
+
let retries = 0;
|
|
199
|
+
let parsedOutput = '';
|
|
200
|
+
|
|
201
|
+
while (true) {
|
|
202
|
+
const systemPrompt = buildReflectorPrompt(level, config.reflectorInstruction);
|
|
203
|
+
const messages = buildReflectorMessages(observations);
|
|
204
|
+
const raw = await complete({ systemPrompt, messages });
|
|
205
|
+
|
|
206
|
+
parsedOutput = parseReflectorOutput(raw);
|
|
207
|
+
|
|
208
|
+
if (validateCompression(parsedOutput, config.reflectionThreshold)) {
|
|
209
|
+
return { observations: parsedOutput, compressionLevel: level };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (level >= MAX_COMPRESSION_LEVEL || retries >= MAX_RETRIES) {
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
level++;
|
|
217
|
+
retries++;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return { observations: parsedOutput, compressionLevel: level };
|
|
221
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the observational memory system.
|
|
3
|
+
*
|
|
4
|
+
* Observational memory is an alternative compaction strategy that replaces
|
|
5
|
+
* Layers 1 and 2 (microcompaction + conversation summarization) with a
|
|
6
|
+
* continuous, background-driven compression system. Two background LLM agents
|
|
7
|
+
* (Observer and Reflector) maintain a compressed event log of the conversation.
|
|
8
|
+
*
|
|
9
|
+
* References:
|
|
10
|
+
* - observational-memory-architecture.md
|
|
11
|
+
* - compaction-strategy.md
|
|
12
|
+
* - context-manager.md
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { AgentMessage } from '../../context-manager.js';
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Configuration
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Consumer-facing configuration for the observational memory system.
|
|
23
|
+
*
|
|
24
|
+
* All fields are optional with sensible defaults. The system adapts to any
|
|
25
|
+
* context window size from 32k to 1M+ through percentage-based thresholds.
|
|
26
|
+
*/
|
|
27
|
+
export interface ObservationalMemoryConfig {
|
|
28
|
+
/**
|
|
29
|
+
* Percentage of total context window utilization that triggers observation
|
|
30
|
+
* activation. When total context (system prompt + slots + observations +
|
|
31
|
+
* messages) exceeds this fraction of the context window, buffered
|
|
32
|
+
* observations activate and raw messages are trimmed.
|
|
33
|
+
* @default 0.9
|
|
34
|
+
*/
|
|
35
|
+
activationThreshold: number;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maximum token count per async buffer observation. Caps how many tokens
|
|
39
|
+
* of unobserved messages a single observer call will process. Prevents
|
|
40
|
+
* oversized observer calls on large context windows.
|
|
41
|
+
* The actual interval is computed dynamically (see Observer System section
|
|
42
|
+
* in architecture doc).
|
|
43
|
+
* Internally clamped to utilityModelContextWindow * 0.6 to ensure the
|
|
44
|
+
* observer input fits within the utility model's context window.
|
|
45
|
+
* @default 30_000
|
|
46
|
+
*/
|
|
47
|
+
bufferTokenCap: number;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Minimum tokens of unobserved messages before a buffer observation runs.
|
|
51
|
+
* Prevents thrashing when the context window is nearly full or on very
|
|
52
|
+
* small windows.
|
|
53
|
+
* @default 5_000
|
|
54
|
+
*/
|
|
55
|
+
bufferMinTokens: number;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Target number of buffer cycles between current utilization and the
|
|
59
|
+
* activation threshold. Higher values mean more frequent, smaller observer
|
|
60
|
+
* calls. Lower values mean fewer, larger observer calls.
|
|
61
|
+
* @default 4
|
|
62
|
+
*/
|
|
63
|
+
bufferTargetCycles: number;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Fraction of the context window at which reflection triggers.
|
|
67
|
+
* When the observation slot exceeds this percentage of the context window,
|
|
68
|
+
* the Reflector condenses it. Scales naturally across all window sizes.
|
|
69
|
+
* Internally clamped to utilityModelContextWindow * 0.5 to ensure the
|
|
70
|
+
* reflector input fits within the utility model's context window.
|
|
71
|
+
* @default 0.20
|
|
72
|
+
*/
|
|
73
|
+
reflectionThreshold: number;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Fraction of reflectionThreshold at which async reflection buffering
|
|
77
|
+
* begins. For example, 0.5 means start background reflection at 50% of
|
|
78
|
+
* the threshold.
|
|
79
|
+
* @default 0.5
|
|
80
|
+
*/
|
|
81
|
+
reflectionBufferActivation: number;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Token budget for previous observations sent to the Observer as context.
|
|
85
|
+
* Provides continuity between observation cycles so the observer does not
|
|
86
|
+
* duplicate already-captured information.
|
|
87
|
+
* @default 2_000
|
|
88
|
+
*/
|
|
89
|
+
previousObserverTokens: number;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Custom instructions appended to the Observer's system prompt.
|
|
93
|
+
* Use for domain-specific observation behavior. Cannot replace the core
|
|
94
|
+
* prompt, only extend it.
|
|
95
|
+
*/
|
|
96
|
+
observerInstruction?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Custom instructions appended to the Reflector's system prompt.
|
|
100
|
+
* Use for domain-specific reflection behavior. Cannot replace the core
|
|
101
|
+
* prompt, only extend it.
|
|
102
|
+
*/
|
|
103
|
+
reflectorInstruction?: string;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Optional recall tool configuration. When provided, Cortex registers a
|
|
107
|
+
* recall tool that enables the agent to search through persisted
|
|
108
|
+
* conversation history. The consumer owns message persistence and search
|
|
109
|
+
* implementation.
|
|
110
|
+
*/
|
|
111
|
+
recall?: RecallConfig;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for the optional recall tool.
|
|
116
|
+
*
|
|
117
|
+
* The consumer provides a search function that Cortex wraps into a tool
|
|
118
|
+
* registered on the agent. Observations include timestamps, enabling
|
|
119
|
+
* temporal anchoring for precise recall queries.
|
|
120
|
+
*/
|
|
121
|
+
export interface RecallConfig {
|
|
122
|
+
/**
|
|
123
|
+
* Search function provided by the consumer. Accepts a query string and
|
|
124
|
+
* optional time range for narrowing results.
|
|
125
|
+
*
|
|
126
|
+
* The consumer owns the search implementation (vector DB, full-text
|
|
127
|
+
* search, SQL, etc.). Cortex only wraps it into a tool.
|
|
128
|
+
*/
|
|
129
|
+
search: (
|
|
130
|
+
query: string,
|
|
131
|
+
options?: { timeRange?: { start?: Date; end?: Date } },
|
|
132
|
+
) => Promise<RecallResult[]>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
// Session State
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Serializable session state for the observational memory system.
|
|
141
|
+
*
|
|
142
|
+
* Saved via `agent.getObservationalMemoryState()` and restored via
|
|
143
|
+
* `agent.restoreObservationalMemoryState()`. The consumer decides where
|
|
144
|
+
* and when to persist this (same pattern as `getConversationHistory()`).
|
|
145
|
+
*/
|
|
146
|
+
export interface ObservationalMemoryState {
|
|
147
|
+
/** Current observation text (the content stored in the _observations slot). */
|
|
148
|
+
observations: string;
|
|
149
|
+
|
|
150
|
+
/** Continuation hints from the last observer run. */
|
|
151
|
+
continuationHint: ContinuationHint | null;
|
|
152
|
+
|
|
153
|
+
/** Current observation token estimate. */
|
|
154
|
+
observationTokenCount: number;
|
|
155
|
+
|
|
156
|
+
/** How many reflection cycles have occurred in this session. */
|
|
157
|
+
generationCount: number;
|
|
158
|
+
|
|
159
|
+
/** Buffered observation chunks not yet activated. */
|
|
160
|
+
bufferedChunks: ObservationChunk[];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// Observation Chunks
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* A buffered observation chunk produced by an async observer call.
|
|
169
|
+
*
|
|
170
|
+
* Chunks accumulate between activation cycles. On activation, completed
|
|
171
|
+
* chunks are merged into the observation slot and their corresponding
|
|
172
|
+
* raw messages are removed from context.
|
|
173
|
+
*/
|
|
174
|
+
export interface ObservationChunk {
|
|
175
|
+
/** The observation text produced by the observer. */
|
|
176
|
+
observations: string;
|
|
177
|
+
|
|
178
|
+
/** Token count of messages that were observed in this chunk. */
|
|
179
|
+
messageTokensObserved: number;
|
|
180
|
+
|
|
181
|
+
/** When this chunk was created. */
|
|
182
|
+
createdAt: Date;
|
|
183
|
+
|
|
184
|
+
/** Current task extracted from this observation. Latest chunk wins on activation. */
|
|
185
|
+
currentTask?: string;
|
|
186
|
+
|
|
187
|
+
/** Suggested response extracted from this observation. Latest chunk wins on activation. */
|
|
188
|
+
suggestedResponse?: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// Events
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Event payload fired when observation activates (messages are compressed
|
|
197
|
+
* and removed from context).
|
|
198
|
+
*
|
|
199
|
+
* Registered via `agent.onObservation()`. Multiple handlers are supported.
|
|
200
|
+
* Consumers can use this to persist compacted messages or coordinate their
|
|
201
|
+
* own compression systems.
|
|
202
|
+
*/
|
|
203
|
+
export interface ObservationEvent {
|
|
204
|
+
/** The raw messages that were compressed and removed from context. */
|
|
205
|
+
compactedMessages: AgentMessage[];
|
|
206
|
+
|
|
207
|
+
/** The observation text those messages were compressed into. */
|
|
208
|
+
observations: string;
|
|
209
|
+
|
|
210
|
+
/** Total context utilization (0-1) at the time of activation. */
|
|
211
|
+
contextUtilization: number;
|
|
212
|
+
|
|
213
|
+
/** Whether this was a sync (blocking) or async (buffered) observation. */
|
|
214
|
+
sync: boolean;
|
|
215
|
+
|
|
216
|
+
/** Timestamp of the observation. */
|
|
217
|
+
timestamp: Date;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Event payload fired after a reflection cycle completes (observations
|
|
222
|
+
* are condensed by the reflector).
|
|
223
|
+
*
|
|
224
|
+
* Registered via `agent.onReflection()`. Multiple handlers are supported.
|
|
225
|
+
* Consumers can use this to coordinate their own compaction timing with
|
|
226
|
+
* Cortex's reflection cycles.
|
|
227
|
+
*/
|
|
228
|
+
export interface ReflectionEvent {
|
|
229
|
+
/** Observations before reflection. */
|
|
230
|
+
previousObservations: string;
|
|
231
|
+
|
|
232
|
+
/** Observations after reflection (condensed). */
|
|
233
|
+
newObservations: string;
|
|
234
|
+
|
|
235
|
+
/** How many reflection generations have occurred in this session. */
|
|
236
|
+
generationCount: number;
|
|
237
|
+
|
|
238
|
+
/** Compression level used (0-4). */
|
|
239
|
+
compressionLevel: number;
|
|
240
|
+
|
|
241
|
+
/** Timestamp of the reflection. */
|
|
242
|
+
timestamp: Date;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
// Recall
|
|
247
|
+
// ---------------------------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* A single result returned from the consumer's recall search function.
|
|
251
|
+
*
|
|
252
|
+
* Contains the content of a past message or tool result along with
|
|
253
|
+
* temporal and classification metadata.
|
|
254
|
+
*/
|
|
255
|
+
export interface RecallResult {
|
|
256
|
+
/** The message or tool result content. */
|
|
257
|
+
content: string;
|
|
258
|
+
|
|
259
|
+
/** When the message occurred. */
|
|
260
|
+
timestamp: Date;
|
|
261
|
+
|
|
262
|
+
/** Type of content returned. */
|
|
263
|
+
type: 'message' | 'tool-result' | 'tool-call';
|
|
264
|
+
|
|
265
|
+
/** Message role, if applicable. */
|
|
266
|
+
role?: 'user' | 'assistant';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// LLM Output Types
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Parsed output from the observer LLM call.
|
|
275
|
+
*
|
|
276
|
+
* The observer produces XML with three sections: observations, current-task,
|
|
277
|
+
* and suggested-response. This type represents the parsed result.
|
|
278
|
+
*/
|
|
279
|
+
export interface ObserverOutput {
|
|
280
|
+
/** Extracted observations in the structured bulleted format. */
|
|
281
|
+
observations: string;
|
|
282
|
+
|
|
283
|
+
/** The agent's current task, if identified by the observer. */
|
|
284
|
+
currentTask?: string;
|
|
285
|
+
|
|
286
|
+
/** A suggested response hint for the agent after observation activates. */
|
|
287
|
+
suggestedResponse?: string;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Parsed output from the reflector LLM call.
|
|
292
|
+
*
|
|
293
|
+
* The reflector produces consolidated observations and reports the
|
|
294
|
+
* compression level it applied.
|
|
295
|
+
*/
|
|
296
|
+
export interface ReflectorOutput {
|
|
297
|
+
/** Consolidated and reorganized observations. */
|
|
298
|
+
observations: string;
|
|
299
|
+
|
|
300
|
+
/** The compression level that was applied (0-4). */
|
|
301
|
+
compressionLevel: number;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ---------------------------------------------------------------------------
|
|
305
|
+
// Internal Types
|
|
306
|
+
// ---------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Continuation hint carried between observer runs and across sessions.
|
|
310
|
+
*
|
|
311
|
+
* Provides the agent with awareness of what it was working on and what
|
|
312
|
+
* it should say next, particularly valuable on session resumption.
|
|
313
|
+
*/
|
|
314
|
+
export interface ContinuationHint {
|
|
315
|
+
/** What the agent is currently working on. */
|
|
316
|
+
currentTask: string;
|
|
317
|
+
|
|
318
|
+
/** Hint for the agent's next message after observation activates. */
|
|
319
|
+
suggestedResponse: string;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Internal state for the buffering coordinator.
|
|
324
|
+
*
|
|
325
|
+
* Tracks the observation watermark, accumulated chunks, and in-flight
|
|
326
|
+
* async operations for both the observer and reflector.
|
|
327
|
+
*/
|
|
328
|
+
export interface BufferState {
|
|
329
|
+
/**
|
|
330
|
+
* Index into agent.state.messages marking where the last completed
|
|
331
|
+
* observation ended. Messages from this index onward are "unobserved."
|
|
332
|
+
*/
|
|
333
|
+
watermark: number;
|
|
334
|
+
|
|
335
|
+
/** Completed observation chunks awaiting activation. */
|
|
336
|
+
chunks: ObservationChunk[];
|
|
337
|
+
|
|
338
|
+
/** Promise for the currently in-flight async observer call, or null. */
|
|
339
|
+
inFlightObserver: Promise<ObserverOutput | null> | null;
|
|
340
|
+
|
|
341
|
+
/** Promise for the currently in-flight async reflector call, or null. */
|
|
342
|
+
inFlightReflector: Promise<ReflectorOutput | null> | null;
|
|
343
|
+
}
|