@cleocode/core 2026.4.35 → 2026.4.37
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/config.d.ts.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/hooks/handlers/conduit-hooks.d.ts +72 -0
- package/dist/hooks/handlers/conduit-hooks.d.ts.map +1 -0
- package/dist/hooks/handlers/conduit-hooks.js +229 -0
- package/dist/hooks/handlers/conduit-hooks.js.map +1 -0
- package/dist/hooks/handlers/index.d.ts +2 -0
- package/dist/hooks/handlers/index.d.ts.map +1 -1
- package/dist/hooks/handlers/index.js +3 -0
- package/dist/hooks/handlers/index.js.map +1 -1
- package/dist/hooks/handlers/session-hooks.d.ts +14 -0
- package/dist/hooks/handlers/session-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/session-hooks.js +33 -0
- package/dist/hooks/handlers/session-hooks.js.map +1 -1
- package/dist/hooks/handlers/task-hooks.d.ts +2 -0
- package/dist/hooks/handlers/task-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/task-hooks.js +14 -0
- package/dist/hooks/handlers/task-hooks.js.map +1 -1
- package/dist/index.js +54928 -46853
- package/dist/index.js.map +4 -4
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/memory/anthropic-key-resolver.d.ts +35 -0
- package/dist/memory/anthropic-key-resolver.d.ts.map +1 -0
- package/dist/memory/anthropic-key-resolver.js +105 -0
- package/dist/memory/anthropic-key-resolver.js.map +1 -0
- package/dist/memory/auto-extract.d.ts +38 -42
- package/dist/memory/auto-extract.d.ts.map +1 -1
- package/dist/memory/auto-extract.js +38 -57
- package/dist/memory/auto-extract.js.map +1 -1
- package/dist/memory/brain-retrieval.d.ts +6 -0
- package/dist/memory/brain-retrieval.d.ts.map +1 -1
- package/dist/memory/brain-retrieval.js +145 -13
- package/dist/memory/brain-retrieval.js.map +1 -1
- package/dist/memory/brain-search.d.ts +82 -15
- package/dist/memory/brain-search.d.ts.map +1 -1
- package/dist/memory/brain-search.js +178 -93
- package/dist/memory/brain-search.js.map +1 -1
- package/dist/memory/engine-compat.d.ts +16 -1
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/engine-compat.js +0 -3
- package/dist/memory/engine-compat.js.map +1 -1
- package/dist/memory/learnings.d.ts.map +1 -1
- package/dist/memory/learnings.js +4 -3
- package/dist/memory/learnings.js.map +1 -1
- package/dist/memory/llm-extraction.d.ts +107 -0
- package/dist/memory/llm-extraction.d.ts.map +1 -0
- package/dist/memory/llm-extraction.js +425 -0
- package/dist/memory/llm-extraction.js.map +1 -0
- package/dist/memory/memory-bridge.js +23 -11
- package/dist/memory/memory-bridge.js.map +1 -1
- package/dist/memory/observer-reflector.d.ts +157 -0
- package/dist/memory/observer-reflector.d.ts.map +1 -0
- package/dist/memory/observer-reflector.js +626 -0
- package/dist/memory/observer-reflector.js.map +1 -0
- package/dist/store/brain-schema.d.ts +131 -0
- package/dist/store/brain-schema.d.ts.map +1 -1
- package/dist/store/brain-schema.js +30 -0
- package/dist/store/brain-schema.js.map +1 -1
- package/dist/store/brain-sqlite.js +41 -1
- package/dist/store/brain-sqlite.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +7 -8
- package/dist/tasks/complete.js.map +1 -1
- package/package.json +13 -12
- package/src/config.ts +7 -0
- package/src/hooks/handlers/__tests__/conduit-hooks.test.ts +356 -0
- package/src/hooks/handlers/conduit-hooks.ts +258 -0
- package/src/hooks/handlers/index.ts +7 -0
- package/src/hooks/handlers/session-hooks.ts +37 -0
- package/src/hooks/handlers/task-hooks.ts +14 -0
- package/src/internal.ts +8 -0
- package/src/memory/__tests__/auto-extract.test.ts +43 -114
- package/src/memory/__tests__/brain-automation.test.ts +16 -39
- package/src/memory/__tests__/brain-rrf.test.ts +431 -0
- package/src/memory/__tests__/llm-extraction.test.ts +342 -0
- package/src/memory/__tests__/observer-reflector.test.ts +475 -0
- package/src/memory/anthropic-key-resolver.ts +113 -0
- package/src/memory/auto-extract.ts +40 -72
- package/src/memory/brain-retrieval.ts +187 -18
- package/src/memory/brain-search.ts +196 -128
- package/src/memory/engine-compat.ts +16 -4
- package/src/memory/learnings.ts +4 -3
- package/src/memory/llm-extraction.ts +524 -0
- package/src/memory/memory-bridge.ts +29 -12
- package/src/memory/observer-reflector.ts +829 -0
- package/src/store/brain-schema.ts +44 -0
- package/src/tasks/complete.ts +7 -10
package/dist/memory/learnings.js
CHANGED
|
@@ -66,8 +66,9 @@ export async function storeLearning(projectRoot, params) {
|
|
|
66
66
|
// memoryType routing (spec §4.1 Decision Tree for memoryType):
|
|
67
67
|
// - source contains 'transcript:ses_' → 'episodic' (event-specific insight)
|
|
68
68
|
// - otherwise → 'semantic' (declarative factual learning)
|
|
69
|
-
//
|
|
70
|
-
|
|
69
|
+
// Owner-stated learnings are ground truth (auto-verified).
|
|
70
|
+
// Transcript-extracted and agent-inferred start unverified — consolidator promotes.
|
|
71
|
+
const isManual = params.source.includes('manual') || params.source.includes('owner');
|
|
71
72
|
const isTranscript = params.source.includes('transcript:ses_');
|
|
72
73
|
const sourceConfidence = isManual
|
|
73
74
|
? 'owner'
|
|
@@ -76,7 +77,7 @@ export async function storeLearning(projectRoot, params) {
|
|
|
76
77
|
: 'agent';
|
|
77
78
|
const memoryTier = isManual ? 'medium' : 'short';
|
|
78
79
|
const memoryType = isTranscript ? 'episodic' : 'semantic';
|
|
79
|
-
const verified =
|
|
80
|
+
const verified = isManual;
|
|
80
81
|
// Compute quality score from confidence, actionability, content richness,
|
|
81
82
|
// and T549 source multiplier.
|
|
82
83
|
const qualityScore = computeLearningQuality({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/memory/learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAqB9D;;GAEG;AACH,SAAS,kBAAkB;IACzB,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,MAA2B;IAClF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAErD,iDAAiD;IACjD,MAAM,iBAAiB,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;IACzD,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5D,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CACtC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,eAAe,CAC1D,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,4DAA4D;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE;YAC1C,UAAU,EAAE,aAAa;SAC1B,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAEzD,mEAAmE;QACnE,eAAe,CACb,WAAW,EACX,YAAY,SAAS,CAAC,EAAE,EAAE,EAC1B,UAAU,EACV,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EACnC,SAAS,CAAC,YAAY,IAAI,GAAG,EAC7B,SAAS,CAAC,OAAO,GAAG,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,EACjD,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,CAC1F,CAAC,KAAK,CAAC,GAAG,EAAE;YACX,iBAAiB;QACnB,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,GAAG,OAAQ;YACX,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,OAAQ,CAAC,mBAAmB,IAAI,IAAI,CAAC;SAClE,CAAC;IACJ,CAAC;IAED,6CAA6C;IAC7C,6FAA6F;IAC7F,sDAAsD;IACtD,uFAAuF;IACvF,+FAA+F;IAC/F,gFAAgF;IAChF,sBAAsB;IACtB,+EAA+E;IAC/E,yFAAyF;IACzF,+DAA+D;IAC/D,8EAA8E;IAC9E,4DAA4D;IAC5D,
|
|
1
|
+
{"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/memory/learnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-driven memory extraction gate.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the legacy keyword regex in `auto-extract.ts`. Takes a session
|
|
5
|
+
* transcript and uses an Anthropic model to extract typed, structured
|
|
6
|
+
* memories (decisions, patterns, learnings, constraints, corrections)
|
|
7
|
+
* with justification, importance score, and referenced entities.
|
|
8
|
+
*
|
|
9
|
+
* Design:
|
|
10
|
+
* - Runs only when `brain.llmExtraction.enabled` is true AND an Anthropic
|
|
11
|
+
* API key is available (from ANTHROPIC_API_KEY env var OR Claude Code
|
|
12
|
+
* credentials at ~/.claude/.credentials.json). Otherwise returns empty.
|
|
13
|
+
* - Uses structured output (JSON schema) for reliable parsing — no regex
|
|
14
|
+
* post-processing.
|
|
15
|
+
* - Never throws — all errors are caught and logged. The pipeline must
|
|
16
|
+
* never block session end.
|
|
17
|
+
* - Store routing: each extracted memory is sent through the existing
|
|
18
|
+
* verify-and-store pipeline. Decisions → brain_decisions, patterns →
|
|
19
|
+
* brain_patterns, learnings/constraints/corrections → brain_learnings.
|
|
20
|
+
* - Source is tagged `agent-llm-extracted` so downstream dedup, quality
|
|
21
|
+
* scoring, and consolidation can distinguish LLM output from other
|
|
22
|
+
* pipelines.
|
|
23
|
+
*
|
|
24
|
+
* Research basis: `.cleo/agent-outputs/R-llm-memory-systems-research.md`
|
|
25
|
+
* (Mem0, Hindsight, Letta, Mastra Observational Memory).
|
|
26
|
+
*/
|
|
27
|
+
import type Anthropic from '@anthropic-ai/sdk';
|
|
28
|
+
/**
|
|
29
|
+
* Allowed extraction types. Each maps to a downstream BRAIN store:
|
|
30
|
+
*
|
|
31
|
+
* - `decision` → brain_decisions (architectural/design decisions)
|
|
32
|
+
* - `pattern` → brain_patterns (procedural how-to knowledge)
|
|
33
|
+
* - `learning` → brain_learnings (semantic facts with confidence)
|
|
34
|
+
* - `constraint` → brain_learnings (rules to follow, high-confidence)
|
|
35
|
+
* - `correction` → brain_patterns (anti-patterns stored with antiPattern field)
|
|
36
|
+
*/
|
|
37
|
+
export type ExtractionType = 'decision' | 'pattern' | 'learning' | 'constraint' | 'correction';
|
|
38
|
+
/**
|
|
39
|
+
* A single memory extracted by the LLM. Fields match the research-approved
|
|
40
|
+
* prompt pattern so downstream storage can route without additional parsing.
|
|
41
|
+
*/
|
|
42
|
+
export interface ExtractedMemory {
|
|
43
|
+
/** Category of knowledge — routes to the correct BRAIN table. */
|
|
44
|
+
type: ExtractionType;
|
|
45
|
+
/** Declarative knowledge content. Capped at 500 characters by the schema. */
|
|
46
|
+
content: string;
|
|
47
|
+
/** Importance score 0.0–1.0; only values ≥ minImportance are persisted. */
|
|
48
|
+
importance: number;
|
|
49
|
+
/** Code symbols, file paths, or concepts referenced by this memory. */
|
|
50
|
+
entities: string[];
|
|
51
|
+
/** Why the model thinks this memory is worth keeping. Capped at 200 chars. */
|
|
52
|
+
justification: string;
|
|
53
|
+
}
|
|
54
|
+
/** Options for extracting memories from a transcript. */
|
|
55
|
+
export interface ExtractFromTranscriptOptions {
|
|
56
|
+
/** CLEO project root. */
|
|
57
|
+
projectRoot: string;
|
|
58
|
+
/** Session ID used as the source tag on stored memories. */
|
|
59
|
+
sessionId: string;
|
|
60
|
+
/** Full session transcript to extract from. */
|
|
61
|
+
transcript: string;
|
|
62
|
+
/**
|
|
63
|
+
* Optional injected Anthropic client — used by tests to mock the SDK
|
|
64
|
+
* without touching the real network. Production callers should omit this
|
|
65
|
+
* and let the function construct its own client from `ANTHROPIC_API_KEY`.
|
|
66
|
+
*/
|
|
67
|
+
client?: Pick<Anthropic, 'messages'>;
|
|
68
|
+
}
|
|
69
|
+
/** Summary of what the LLM extraction pipeline produced. */
|
|
70
|
+
export interface ExtractionReport {
|
|
71
|
+
/** Count of extractions returned by the model before filtering. */
|
|
72
|
+
extractedCount: number;
|
|
73
|
+
/** Count persisted after importance filter and verify-and-store gate. */
|
|
74
|
+
storedCount: number;
|
|
75
|
+
/** Count merged into existing entries by the verify-and-store gate. */
|
|
76
|
+
mergedCount: number;
|
|
77
|
+
/** Count rejected (below minImportance, gate-rejected, or errored). */
|
|
78
|
+
rejectedCount: number;
|
|
79
|
+
/** Non-fatal warnings collected during extraction. */
|
|
80
|
+
warnings: string[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract and persist structured memories from a session transcript using
|
|
84
|
+
* an Anthropic model.
|
|
85
|
+
*
|
|
86
|
+
* This is the sole entry point replacing the legacy keyword-regex extractor.
|
|
87
|
+
* Callers (e.g. the session-end hook) invoke this and the function handles:
|
|
88
|
+
* 1. Config lookup (brain.llmExtraction.enabled, model, thresholds)
|
|
89
|
+
* 2. API key detection (skips extraction if missing)
|
|
90
|
+
* 3. Transcript clipping to stay within token budget
|
|
91
|
+
* 4. Structured-output LLM call with the research-approved prompt
|
|
92
|
+
* 5. Importance filtering (below minImportance → dropped)
|
|
93
|
+
* 6. Storage routing through the existing verify-and-store pipeline
|
|
94
|
+
*
|
|
95
|
+
* Never throws. Returns an ExtractionReport describing what was stored.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* await extractFromTranscript({
|
|
100
|
+
* projectRoot: '/path/to/project',
|
|
101
|
+
* sessionId: 'ses_20260413192026_519188',
|
|
102
|
+
* transcript: rawTranscript,
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function extractFromTranscript(options: ExtractFromTranscriptOptions): Promise<ExtractionReport>;
|
|
107
|
+
//# sourceMappingURL=llm-extraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-extraction.d.ts","sourceRoot":"","sources":["../../src/memory/llm-extraction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAQ/C;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;AAE/F;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,IAAI,EAAE,cAAc,CAAC;IACrB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,yDAAyD;AACzD,MAAM,WAAW,4BAA4B;IAC3C,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;CACtC;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAuOD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CA8G3B"}
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-driven memory extraction gate.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the legacy keyword regex in `auto-extract.ts`. Takes a session
|
|
5
|
+
* transcript and uses an Anthropic model to extract typed, structured
|
|
6
|
+
* memories (decisions, patterns, learnings, constraints, corrections)
|
|
7
|
+
* with justification, importance score, and referenced entities.
|
|
8
|
+
*
|
|
9
|
+
* Design:
|
|
10
|
+
* - Runs only when `brain.llmExtraction.enabled` is true AND an Anthropic
|
|
11
|
+
* API key is available (from ANTHROPIC_API_KEY env var OR Claude Code
|
|
12
|
+
* credentials at ~/.claude/.credentials.json). Otherwise returns empty.
|
|
13
|
+
* - Uses structured output (JSON schema) for reliable parsing — no regex
|
|
14
|
+
* post-processing.
|
|
15
|
+
* - Never throws — all errors are caught and logged. The pipeline must
|
|
16
|
+
* never block session end.
|
|
17
|
+
* - Store routing: each extracted memory is sent through the existing
|
|
18
|
+
* verify-and-store pipeline. Decisions → brain_decisions, patterns →
|
|
19
|
+
* brain_patterns, learnings/constraints/corrections → brain_learnings.
|
|
20
|
+
* - Source is tagged `agent-llm-extracted` so downstream dedup, quality
|
|
21
|
+
* scoring, and consolidation can distinguish LLM output from other
|
|
22
|
+
* pipelines.
|
|
23
|
+
*
|
|
24
|
+
* Research basis: `.cleo/agent-outputs/R-llm-memory-systems-research.md`
|
|
25
|
+
* (Mem0, Hindsight, Letta, Mastra Observational Memory).
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
import { resolveAnthropicApiKey } from './anthropic-key-resolver.js';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Zod schema for structured output
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
const ExtractedMemorySchema = z.object({
|
|
33
|
+
type: z.enum(['decision', 'pattern', 'learning', 'constraint', 'correction']),
|
|
34
|
+
content: z.string().min(1).max(500),
|
|
35
|
+
importance: z.number().min(0).max(1),
|
|
36
|
+
entities: z.array(z.string()).max(20),
|
|
37
|
+
justification: z.string().min(1).max(200),
|
|
38
|
+
});
|
|
39
|
+
const ExtractionResponseSchema = z.object({
|
|
40
|
+
memories: z.array(ExtractedMemorySchema).max(20),
|
|
41
|
+
});
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Prompt
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
const SYSTEM_PROMPT = `You are extracting durable knowledge from a coding session transcript.
|
|
46
|
+
Extract ONLY high-value items. Reject noise (greetings, meta-commentary, transient state).
|
|
47
|
+
|
|
48
|
+
For each extraction provide:
|
|
49
|
+
- type: decision|pattern|learning|constraint|correction
|
|
50
|
+
- content: the knowledge itself (<=500 chars, declarative form)
|
|
51
|
+
- importance: 0.0-1.0 (only >=0.6 will be stored)
|
|
52
|
+
- entities: code symbols, files, concepts mentioned
|
|
53
|
+
- justification: why this is worth remembering (<=200 chars)
|
|
54
|
+
|
|
55
|
+
Type definitions:
|
|
56
|
+
- decision: architectural or design choice with rationale ("We chose X because Y")
|
|
57
|
+
- pattern: recurring approach that works ("When X, do Y because Z")
|
|
58
|
+
- learning: factual knowledge gained ("X depends on Y via Z")
|
|
59
|
+
- constraint: rule/limitation discovered ("X must always Y")
|
|
60
|
+
- correction: anti-pattern to avoid ("Avoid X because Y; use Z instead")
|
|
61
|
+
|
|
62
|
+
Rules:
|
|
63
|
+
- Capture the WHY, not just the WHAT
|
|
64
|
+
- If nothing of durable value exists in the transcript, return an empty array
|
|
65
|
+
- Prefer fewer high-quality extractions over many low-quality ones
|
|
66
|
+
- Ignore: tool output noise, routine status messages, file reads without a finding
|
|
67
|
+
- Maximum 7 extractions per call`;
|
|
68
|
+
function buildUserPrompt(sessionId, transcript, maxExtractions) {
|
|
69
|
+
return `Session ID: ${sessionId}
|
|
70
|
+
|
|
71
|
+
Transcript:
|
|
72
|
+
${transcript}
|
|
73
|
+
|
|
74
|
+
Extract up to ${maxExtractions} high-value memories. Return empty array if nothing valuable.`;
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Helpers
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Trim a transcript to a maximum character budget, preserving the head and tail
|
|
81
|
+
* (the ends typically contain the request and the final outcome).
|
|
82
|
+
*/
|
|
83
|
+
function clipTranscript(transcript, maxChars) {
|
|
84
|
+
if (transcript.length <= maxChars)
|
|
85
|
+
return transcript;
|
|
86
|
+
const half = Math.floor(maxChars / 2) - 64;
|
|
87
|
+
const head = transcript.slice(0, half);
|
|
88
|
+
const tail = transcript.slice(-half);
|
|
89
|
+
return `${head}\n\n[... ${transcript.length - maxChars} chars omitted ...]\n\n${tail}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build a MemoryCandidate for the verify-and-store gate from an
|
|
93
|
+
* ExtractedMemory plus session context.
|
|
94
|
+
*
|
|
95
|
+
* Routing:
|
|
96
|
+
* - decision → semantic memory (downstream storeLearning is semantic,
|
|
97
|
+
* but decisions go through storeDecision via routing below)
|
|
98
|
+
* - pattern → procedural (goes to brain_patterns via extraction gate)
|
|
99
|
+
* - learning → semantic (brain_learnings)
|
|
100
|
+
* - constraint → semantic (brain_learnings, with higher confidence)
|
|
101
|
+
* - correction → procedural (brain_patterns with antiPattern flag)
|
|
102
|
+
*/
|
|
103
|
+
async function storeExtracted(projectRoot, sessionId, memory) {
|
|
104
|
+
const source = `agent-llm-extracted:${sessionId}`;
|
|
105
|
+
// Decisions use storeDecision directly so contextPhase + type flow through.
|
|
106
|
+
if (memory.type === 'decision') {
|
|
107
|
+
const { storeDecision } = await import('./decisions.js');
|
|
108
|
+
try {
|
|
109
|
+
// decision text is the content before " because "; rationale follows.
|
|
110
|
+
const { decisionText, rationale } = splitDecisionContent(memory.content);
|
|
111
|
+
await storeDecision(projectRoot, {
|
|
112
|
+
type: 'technical',
|
|
113
|
+
decision: decisionText,
|
|
114
|
+
rationale,
|
|
115
|
+
confidence: mapImportanceToConfidence(memory.importance),
|
|
116
|
+
});
|
|
117
|
+
return 'stored';
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return 'rejected';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Corrections map to patterns with antiPattern + mitigation fields.
|
|
124
|
+
if (memory.type === 'correction') {
|
|
125
|
+
const { storePattern } = await import('./patterns.js');
|
|
126
|
+
try {
|
|
127
|
+
await storePattern(projectRoot, {
|
|
128
|
+
type: 'failure',
|
|
129
|
+
pattern: memory.content,
|
|
130
|
+
context: `From session ${sessionId}. ${memory.justification}`,
|
|
131
|
+
antiPattern: memory.content,
|
|
132
|
+
mitigation: memory.justification,
|
|
133
|
+
impact: memory.importance >= 0.8 ? 'high' : memory.importance >= 0.6 ? 'medium' : 'low',
|
|
134
|
+
source,
|
|
135
|
+
});
|
|
136
|
+
return 'stored';
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return 'rejected';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Patterns map to brain_patterns.
|
|
143
|
+
if (memory.type === 'pattern') {
|
|
144
|
+
const { storePattern } = await import('./patterns.js');
|
|
145
|
+
try {
|
|
146
|
+
await storePattern(projectRoot, {
|
|
147
|
+
type: 'workflow',
|
|
148
|
+
pattern: memory.content,
|
|
149
|
+
context: `From session ${sessionId}. ${memory.justification}`,
|
|
150
|
+
impact: memory.importance >= 0.8 ? 'high' : memory.importance >= 0.6 ? 'medium' : 'low',
|
|
151
|
+
source,
|
|
152
|
+
});
|
|
153
|
+
return 'stored';
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return 'rejected';
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Learnings and constraints map to brain_learnings.
|
|
160
|
+
const { storeLearning } = await import('./learnings.js');
|
|
161
|
+
try {
|
|
162
|
+
await storeLearning(projectRoot, {
|
|
163
|
+
insight: memory.content,
|
|
164
|
+
source,
|
|
165
|
+
confidence: memory.type === 'constraint' ? Math.max(memory.importance, 0.8) : memory.importance,
|
|
166
|
+
actionable: memory.type === 'constraint',
|
|
167
|
+
});
|
|
168
|
+
return 'stored';
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return 'rejected';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Split a decision extraction into decision + rationale at the first " because "
|
|
176
|
+
* marker. When no marker exists, the full content becomes the decision and the
|
|
177
|
+
* justification becomes the rationale.
|
|
178
|
+
*/
|
|
179
|
+
function splitDecisionContent(content) {
|
|
180
|
+
const idx = content.toLowerCase().indexOf(' because ');
|
|
181
|
+
if (idx === -1) {
|
|
182
|
+
return { decisionText: content.trim(), rationale: 'See justification' };
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
decisionText: content.slice(0, idx).trim(),
|
|
186
|
+
rationale: content.slice(idx + 1).trim(),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Map an importance score to a BrainDecisionRow confidence bucket.
|
|
191
|
+
* Importance is continuous 0–1; confidence is `low` | `medium` | `high`.
|
|
192
|
+
*/
|
|
193
|
+
function mapImportanceToConfidence(importance) {
|
|
194
|
+
if (importance >= 0.8)
|
|
195
|
+
return 'high';
|
|
196
|
+
if (importance >= 0.6)
|
|
197
|
+
return 'medium';
|
|
198
|
+
return 'low';
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// Anthropic client construction
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
/**
|
|
204
|
+
* Lazily import and instantiate the Anthropic SDK.
|
|
205
|
+
*
|
|
206
|
+
* Resolves the API key from env or Claude Code credentials. Returns null
|
|
207
|
+
* when no key is available so callers can gracefully degrade to no-op.
|
|
208
|
+
* The SDK is imported via dynamic import so projects that do not use the
|
|
209
|
+
* LLM extraction gate don't pay the load cost at startup.
|
|
210
|
+
*/
|
|
211
|
+
async function buildAnthropicClient() {
|
|
212
|
+
const apiKey = resolveAnthropicApiKey();
|
|
213
|
+
if (!apiKey) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
const AnthropicModule = await import('@anthropic-ai/sdk');
|
|
218
|
+
const Ctor = AnthropicModule.default ??
|
|
219
|
+
AnthropicModule;
|
|
220
|
+
return new Ctor({ apiKey });
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Build the zodOutputFormat helper asynchronously (dynamic import matches
|
|
228
|
+
* SDK's subpath export style). Returns null when the SDK cannot be loaded.
|
|
229
|
+
*/
|
|
230
|
+
async function buildZodFormat(schema) {
|
|
231
|
+
try {
|
|
232
|
+
const helpers = await import('@anthropic-ai/sdk/helpers/zod');
|
|
233
|
+
return helpers.zodOutputFormat(schema);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// Public API
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
/**
|
|
243
|
+
* Extract and persist structured memories from a session transcript using
|
|
244
|
+
* an Anthropic model.
|
|
245
|
+
*
|
|
246
|
+
* This is the sole entry point replacing the legacy keyword-regex extractor.
|
|
247
|
+
* Callers (e.g. the session-end hook) invoke this and the function handles:
|
|
248
|
+
* 1. Config lookup (brain.llmExtraction.enabled, model, thresholds)
|
|
249
|
+
* 2. API key detection (skips extraction if missing)
|
|
250
|
+
* 3. Transcript clipping to stay within token budget
|
|
251
|
+
* 4. Structured-output LLM call with the research-approved prompt
|
|
252
|
+
* 5. Importance filtering (below minImportance → dropped)
|
|
253
|
+
* 6. Storage routing through the existing verify-and-store pipeline
|
|
254
|
+
*
|
|
255
|
+
* Never throws. Returns an ExtractionReport describing what was stored.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```ts
|
|
259
|
+
* await extractFromTranscript({
|
|
260
|
+
* projectRoot: '/path/to/project',
|
|
261
|
+
* sessionId: 'ses_20260413192026_519188',
|
|
262
|
+
* transcript: rawTranscript,
|
|
263
|
+
* });
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export async function extractFromTranscript(options) {
|
|
267
|
+
const report = {
|
|
268
|
+
extractedCount: 0,
|
|
269
|
+
storedCount: 0,
|
|
270
|
+
mergedCount: 0,
|
|
271
|
+
rejectedCount: 0,
|
|
272
|
+
warnings: [],
|
|
273
|
+
};
|
|
274
|
+
const { projectRoot, sessionId, transcript } = options;
|
|
275
|
+
if (typeof transcript !== 'string' || transcript.trim().length === 0) {
|
|
276
|
+
return report;
|
|
277
|
+
}
|
|
278
|
+
// -------------------------------------------------------------------------
|
|
279
|
+
// Config lookup
|
|
280
|
+
// -------------------------------------------------------------------------
|
|
281
|
+
const { loadConfig } = await import('../config.js');
|
|
282
|
+
let config;
|
|
283
|
+
try {
|
|
284
|
+
config = await loadConfig(projectRoot);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
report.warnings.push('config load failed, using defaults');
|
|
288
|
+
config = undefined;
|
|
289
|
+
}
|
|
290
|
+
const llmCfg = config?.brain?.llmExtraction;
|
|
291
|
+
const enabled = llmCfg?.enabled ?? true;
|
|
292
|
+
if (!enabled) {
|
|
293
|
+
report.warnings.push('llmExtraction.enabled=false');
|
|
294
|
+
return report;
|
|
295
|
+
}
|
|
296
|
+
const model = llmCfg?.model ?? 'claude-haiku-4-5-20251001';
|
|
297
|
+
const minImportance = llmCfg?.minImportance ?? 0.6;
|
|
298
|
+
const maxExtractions = llmCfg?.maxExtractions ?? 7;
|
|
299
|
+
const maxTranscriptChars = llmCfg?.maxTranscriptChars ?? 60000;
|
|
300
|
+
// -------------------------------------------------------------------------
|
|
301
|
+
// Client construction (allow injection for tests)
|
|
302
|
+
// -------------------------------------------------------------------------
|
|
303
|
+
const client = options.client ?? (await buildAnthropicClient());
|
|
304
|
+
if (!client) {
|
|
305
|
+
report.warnings.push('No Anthropic API key found (checked ANTHROPIC_API_KEY env and ~/.claude/.credentials.json) — extraction skipped');
|
|
306
|
+
return report;
|
|
307
|
+
}
|
|
308
|
+
// -------------------------------------------------------------------------
|
|
309
|
+
// Call the model
|
|
310
|
+
// -------------------------------------------------------------------------
|
|
311
|
+
const clipped = clipTranscript(transcript, maxTranscriptChars);
|
|
312
|
+
const userPrompt = buildUserPrompt(sessionId, clipped, maxExtractions);
|
|
313
|
+
let extracted = [];
|
|
314
|
+
try {
|
|
315
|
+
const format = await buildZodFormat(ExtractionResponseSchema);
|
|
316
|
+
if (format) {
|
|
317
|
+
// Preferred path: structured output via SDK helper.
|
|
318
|
+
const messages = client.messages;
|
|
319
|
+
const response = await messages.parse({
|
|
320
|
+
model,
|
|
321
|
+
max_tokens: 4096,
|
|
322
|
+
system: SYSTEM_PROMPT,
|
|
323
|
+
messages: [{ role: 'user', content: userPrompt }],
|
|
324
|
+
output_config: { format },
|
|
325
|
+
});
|
|
326
|
+
extracted = response.parsed_output?.memories ?? [];
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
// Degraded path: plain messages.create + manual JSON parsing.
|
|
330
|
+
extracted = await extractViaPlainCall(client, model, userPrompt);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
335
|
+
report.warnings.push(`extraction call failed: ${message}`);
|
|
336
|
+
return report;
|
|
337
|
+
}
|
|
338
|
+
report.extractedCount = extracted.length;
|
|
339
|
+
// -------------------------------------------------------------------------
|
|
340
|
+
// Filter + store
|
|
341
|
+
// -------------------------------------------------------------------------
|
|
342
|
+
for (const memory of extracted) {
|
|
343
|
+
if (memory.importance < minImportance) {
|
|
344
|
+
report.rejectedCount += 1;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const outcome = await storeExtracted(projectRoot, sessionId, memory);
|
|
349
|
+
if (outcome === 'stored')
|
|
350
|
+
report.storedCount += 1;
|
|
351
|
+
else if (outcome === 'merged')
|
|
352
|
+
report.mergedCount += 1;
|
|
353
|
+
else
|
|
354
|
+
report.rejectedCount += 1;
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
358
|
+
report.warnings.push(`store failed: ${message}`);
|
|
359
|
+
report.rejectedCount += 1;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return report;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Fallback extraction path: calls messages.create and parses the response
|
|
366
|
+
* content manually. Used when the zod helper cannot be loaded (e.g. SDK
|
|
367
|
+
* version mismatch) but the messages.create API is still available.
|
|
368
|
+
*/
|
|
369
|
+
async function extractViaPlainCall(client, model, userPrompt) {
|
|
370
|
+
const response = await client.messages.create({
|
|
371
|
+
model,
|
|
372
|
+
max_tokens: 4096,
|
|
373
|
+
system: `${SYSTEM_PROMPT}\n\nReturn ONLY a JSON object of shape {"memories": [...]} with no prose.`,
|
|
374
|
+
messages: [{ role: 'user', content: userPrompt }],
|
|
375
|
+
});
|
|
376
|
+
const text = extractTextFromResponse(response);
|
|
377
|
+
if (!text)
|
|
378
|
+
return [];
|
|
379
|
+
const parsed = safeJsonParse(text);
|
|
380
|
+
if (!parsed)
|
|
381
|
+
return [];
|
|
382
|
+
const validated = ExtractionResponseSchema.safeParse(parsed);
|
|
383
|
+
if (!validated.success)
|
|
384
|
+
return [];
|
|
385
|
+
return validated.data.memories;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Pull plain text from a messages.create response. Anthropic returns a
|
|
389
|
+
* content array; we concatenate all text blocks.
|
|
390
|
+
*/
|
|
391
|
+
function extractTextFromResponse(response) {
|
|
392
|
+
const content = response?.content;
|
|
393
|
+
if (!Array.isArray(content))
|
|
394
|
+
return '';
|
|
395
|
+
return content
|
|
396
|
+
.filter((block) => block?.type === 'text' && typeof block.text === 'string')
|
|
397
|
+
.map((block) => block.text ?? '')
|
|
398
|
+
.join('');
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Parse JSON, extracting the first {...} object even if the model wrapped
|
|
402
|
+
* it in markdown fences or added prose. Returns null on any failure.
|
|
403
|
+
*/
|
|
404
|
+
function safeJsonParse(text) {
|
|
405
|
+
const trimmed = text.trim();
|
|
406
|
+
// Direct parse first
|
|
407
|
+
try {
|
|
408
|
+
return JSON.parse(trimmed);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// Fall through to extraction
|
|
412
|
+
}
|
|
413
|
+
// Extract between first { and last }
|
|
414
|
+
const first = trimmed.indexOf('{');
|
|
415
|
+
const last = trimmed.lastIndexOf('}');
|
|
416
|
+
if (first === -1 || last === -1 || last < first)
|
|
417
|
+
return null;
|
|
418
|
+
try {
|
|
419
|
+
return JSON.parse(trimmed.slice(first, last + 1));
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=llm-extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-extraction.js","sourceRoot":"","sources":["../../src/memory/llm-extraction.ts"],"names":[],"mappings":"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"}
|