claude-brain 0.22.3 → 0.22.4
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/VERSION +1 -1
- package/package.json +1 -1
- package/src/routing/response-filter.ts +3 -1
- package/src/routing/router.ts +48 -7
- package/src/server/handlers/tools/brain.ts +3 -2
- package/src/server/handlers/tools/schemas.ts +2 -1
- package/src/server/http-api.ts +1 -1
- package/src/server/utils/memory-indicator.ts +4 -3
- package/src/tools/schemas.ts +5 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.22.
|
|
1
|
+
0.22.4
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export interface FilterableResult {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface FilteredResult {
|
|
18
|
+
id?: string
|
|
18
19
|
content: string
|
|
19
20
|
score: number
|
|
20
21
|
source: string
|
|
@@ -74,8 +75,9 @@ export class ResponseFilter {
|
|
|
74
75
|
// 5. Limit to 5 results
|
|
75
76
|
filtered = filtered.slice(0, 5)
|
|
76
77
|
|
|
77
|
-
// 6. Add one-line relevance explanation per result
|
|
78
|
+
// 6. Add one-line relevance explanation per result (preserve id from metadata)
|
|
78
79
|
return filtered.map(r => ({
|
|
80
|
+
id: (r.metadata as any)?.id || (r.metadata as any)?.decision_id,
|
|
79
81
|
content: r.content,
|
|
80
82
|
score: r.score,
|
|
81
83
|
source: r.source,
|
package/src/routing/router.ts
CHANGED
|
@@ -39,6 +39,7 @@ const UPDATE_MIN_SIMILARITY = 0.3
|
|
|
39
39
|
export interface BrainInput {
|
|
40
40
|
message: string
|
|
41
41
|
project?: string
|
|
42
|
+
action?: 'auto' | 'store' | 'recall' | 'update' | 'delete'
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
/** Recently stored decision for recency fast path (Bug 4 fix) */
|
|
@@ -84,17 +85,44 @@ export class BrainRouter {
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
async route(input: BrainInput): Promise<BrainResponse> {
|
|
87
|
-
const { message, project: inputProject } = input
|
|
88
|
+
const { message, project: inputProject, action } = input
|
|
88
89
|
|
|
89
|
-
//
|
|
90
|
-
const classification = this.classifier.classify(message)
|
|
91
|
-
this.logger.debug({ intent: classification.primary, confidence: classification.confidence }, 'Intent classified')
|
|
92
|
-
|
|
93
|
-
// Extract entities
|
|
90
|
+
// Extract entities (needed for all paths)
|
|
94
91
|
const entities = await this.entityExtractor.extract(message, inputProject)
|
|
95
92
|
const project = entities.project || inputProject
|
|
96
93
|
this.logger.debug({ project, technologies: entities.technologies }, 'Entities extracted')
|
|
97
94
|
|
|
95
|
+
// P1: Explicit action override — bypass intent classifier entirely
|
|
96
|
+
if (action && action !== 'auto') {
|
|
97
|
+
this.logger.debug({ action }, 'Using explicit action override')
|
|
98
|
+
try {
|
|
99
|
+
switch (action) {
|
|
100
|
+
case 'store':
|
|
101
|
+
return this.handleStoreThis(message, project, entities)
|
|
102
|
+
case 'recall':
|
|
103
|
+
return this.handleContextNeeded(message, project, entities)
|
|
104
|
+
case 'update':
|
|
105
|
+
return this.handleUpdateMemory(message, project, entities)
|
|
106
|
+
case 'delete':
|
|
107
|
+
return this.handleDeleteMemory(message, project, entities)
|
|
108
|
+
default:
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
this.logger.error({ error, action }, 'Router action override error')
|
|
113
|
+
return {
|
|
114
|
+
action: 'none',
|
|
115
|
+
summary: `Error processing ${action} request`,
|
|
116
|
+
content: `Failed to process: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
117
|
+
relevantItems: 0
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Classify intent
|
|
123
|
+
const classification = this.classifier.classify(message)
|
|
124
|
+
this.logger.debug({ intent: classification.primary, confidence: classification.confidence }, 'Intent classified')
|
|
125
|
+
|
|
98
126
|
// Route to handler
|
|
99
127
|
try {
|
|
100
128
|
switch (classification.primary) {
|
|
@@ -383,7 +411,20 @@ export class BrainRouter {
|
|
|
383
411
|
})
|
|
384
412
|
}
|
|
385
413
|
|
|
386
|
-
|
|
414
|
+
const response = this.responseFilter.synthesize(tiers, message, displayProject)
|
|
415
|
+
|
|
416
|
+
// P0: When no results found and message looks like a plain statement (not a question),
|
|
417
|
+
// add a hint that the user may have intended to store it
|
|
418
|
+
if (response.action === 'none' && response.relevantItems === 0) {
|
|
419
|
+
const isPlainStatement = message.length > 15 &&
|
|
420
|
+
!message.trim().endsWith('?') &&
|
|
421
|
+
message.split(/\s+/).length > 3
|
|
422
|
+
if (isPlainStatement) {
|
|
423
|
+
response.content += `\n\n**Tip:** If you meant to save this, try:\n- \`brain("Remember: ${message.slice(0, 60)}")\`\n- Or use \`action: "store"\` to force storage: \`brain({ message: "...", action: "store" })\``
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return response
|
|
387
428
|
}
|
|
388
429
|
|
|
389
430
|
/**
|
|
@@ -22,19 +22,20 @@ export async function handleBrain(
|
|
|
22
22
|
): Promise<ToolResponse> {
|
|
23
23
|
try {
|
|
24
24
|
const input = ToolValidator.validate(args, BrainSchema)
|
|
25
|
-
const { message, project } = input
|
|
25
|
+
const { message, project, action } = input
|
|
26
26
|
|
|
27
27
|
logger.debug(
|
|
28
28
|
{
|
|
29
29
|
messageLength: message.length,
|
|
30
30
|
project,
|
|
31
|
+
action,
|
|
31
32
|
messagePreview: message.slice(0, 80)
|
|
32
33
|
},
|
|
33
34
|
'Brain tool called'
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
const router = getBrainRouter(logger)
|
|
37
|
-
const response = await router.route({ message, project })
|
|
38
|
+
const response = await router.route({ message, project, action })
|
|
38
39
|
|
|
39
40
|
logger.info(
|
|
40
41
|
{
|
|
@@ -137,7 +137,8 @@ export const GetPhase12StatusSchema = z.object({})
|
|
|
137
137
|
|
|
138
138
|
export const BrainSchema = z.object({
|
|
139
139
|
message: z.string().min(1, 'message is required'),
|
|
140
|
-
project: z.string().optional()
|
|
140
|
+
project: z.string().optional(),
|
|
141
|
+
action: z.enum(['auto', 'store', 'recall', 'update', 'delete']).optional()
|
|
141
142
|
})
|
|
142
143
|
|
|
143
144
|
// ============================================================================
|
package/src/server/http-api.ts
CHANGED
|
@@ -814,7 +814,7 @@ export class HttpApiServer {
|
|
|
814
814
|
memoryService.recallSimilar(projectName || 'recent work', {
|
|
815
815
|
project: projectName,
|
|
816
816
|
limit: 5,
|
|
817
|
-
minSimilarity: 0.
|
|
817
|
+
minSimilarity: 0.65,
|
|
818
818
|
}),
|
|
819
819
|
memoryService.getPatterns(projectName, { limit: 5 }),
|
|
820
820
|
])
|
|
@@ -16,13 +16,14 @@ const ANSI = {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Memory indicator banner shown when Claude Brain provides helpful data
|
|
19
|
+
* Note: No ANSI codes — MCP tool responses should be plain text/markdown
|
|
19
20
|
*/
|
|
20
|
-
export const MEMORY_HELPED_BANNER =
|
|
21
|
+
export const MEMORY_HELPED_BANNER = '🧠 MEMORY ASSISTED'
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Alternative shorter indicator
|
|
24
25
|
*/
|
|
25
|
-
export const MEMORY_HELPED_SHORT =
|
|
26
|
+
export const MEMORY_HELPED_SHORT = '[memory-assisted]'
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Wrap content with the memory helped indicator
|
|
@@ -63,7 +64,7 @@ export function formatMemoryStats(stats: {
|
|
|
63
64
|
|
|
64
65
|
if (parts.length === 0) return ''
|
|
65
66
|
|
|
66
|
-
return
|
|
67
|
+
return `📊 Retrieved: ${parts.join(', ')}`
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
/**
|
package/src/tools/schemas.ts
CHANGED
|
@@ -601,6 +601,11 @@ export const TOOLS = {
|
|
|
601
601
|
project: {
|
|
602
602
|
type: 'string',
|
|
603
603
|
description: 'Project name (IMPORTANT: pass this to scope memories correctly, e.g. "my-app"). Auto-detected from message if omitted, defaults to "general".'
|
|
604
|
+
},
|
|
605
|
+
action: {
|
|
606
|
+
type: 'string',
|
|
607
|
+
enum: ['auto', 'store', 'recall', 'update', 'delete'],
|
|
608
|
+
description: 'Force a specific action instead of auto-detecting intent. "store" = always save, "recall" = always search, "update" = modify last stored, "delete" = remove. Default: auto (use intent classifier).'
|
|
604
609
|
}
|
|
605
610
|
},
|
|
606
611
|
required: ['message']
|