|
1 | | -// altimate_change - Training prompt injection for AI Teammate learned knowledge |
2 | | -import { TrainingStore, type TrainingEntry } from "./store" |
3 | | -import { TRAINING_BUDGET, type TrainingKind } from "./types" |
4 | | - |
5 | | -const KIND_HEADERS: Record<TrainingKind, { header: string; instruction: string }> = { |
6 | | - pattern: { |
7 | | - header: "Learned Patterns", |
8 | | - instruction: "Follow these patterns when creating similar artifacts. They were learned from the user's codebase.", |
9 | | - }, |
10 | | - rule: { |
11 | | - header: "Learned Rules", |
12 | | - instruction: "Always follow these rules. They were taught by the user through corrections and explicit instruction.", |
13 | | - }, |
14 | | - glossary: { |
15 | | - header: "Domain Glossary", |
16 | | - instruction: "Use these definitions when discussing business concepts. They are specific to the user's domain.", |
17 | | - }, |
18 | | - standard: { |
19 | | - header: "Team Standards", |
20 | | - instruction: "Enforce these standards in code reviews and when writing new code. They were loaded from team documentation.", |
21 | | - }, |
22 | | - context: { |
23 | | - header: "Domain Context", |
24 | | - instruction: "Use this background knowledge to inform your reasoning. Not directly enforceable, but critical for understanding 'why'.", |
25 | | - }, |
26 | | - playbook: { |
27 | | - header: "Playbooks", |
28 | | - instruction: "Follow these step-by-step procedures when handling the described scenarios.", |
29 | | - }, |
30 | | -} |
31 | | - |
32 | | -// Track which entries have been applied this session to avoid double-counting |
33 | | -const appliedThisSession = new Set<string>() |
| 1 | +// altimate_change - Training prompt (deprecated — delegates to unified MemoryPrompt.inject) |
| 2 | +// Kept for backward compatibility with training tools (budgetUsage) and tests. |
| 3 | +import { MemoryPrompt } from "../../memory/prompt" |
| 4 | +import { TRAINING_BUDGET } from "./types" |
| 5 | +import type { TrainingEntry } from "./store" |
34 | 6 |
|
35 | 7 | export namespace TrainingPrompt { |
| 8 | + /** Format a training entry for display. */ |
36 | 9 | export function formatEntry(entry: TrainingEntry): string { |
37 | 10 | const meta = entry.meta.applied > 0 ? ` (applied ${entry.meta.applied}x)` : "" |
38 | 11 | return `#### ${entry.name}${meta}\n${entry.content}` |
39 | 12 | } |
40 | 13 |
|
41 | | - /** Reset session tracking (call at session start) */ |
| 14 | + /** @deprecated — Use MemoryPrompt.resetSession(). Kept for backward compat. */ |
42 | 15 | export function resetSession(): void { |
43 | | - appliedThisSession.clear() |
| 16 | + MemoryPrompt.resetSession() |
44 | 17 | } |
45 | 18 |
|
| 19 | + /** @deprecated — Use MemoryPrompt.inject() with context. Kept for training tool compat. */ |
46 | 20 | export async function inject(budget: number = TRAINING_BUDGET): Promise<string> { |
47 | | - const entries = await TrainingStore.list() |
48 | | - if (entries.length === 0) return "" |
49 | | - |
50 | | - const grouped = new Map<TrainingKind, TrainingEntry[]>() |
51 | | - for (const entry of entries) { |
52 | | - const list = grouped.get(entry.kind) ?? [] |
53 | | - list.push(entry) |
54 | | - grouped.set(entry.kind, list) |
55 | | - } |
56 | | - |
57 | | - const header = |
58 | | - "## Teammate Training\n\nYou have been trained on the following knowledge by your team. Apply it consistently.\n" |
59 | | - let result = header |
60 | | - let used = header.length |
61 | | - const injected: TrainingEntry[] = [] |
62 | | - |
63 | | - for (const kind of ["rule", "pattern", "standard", "glossary", "context", "playbook"] as TrainingKind[]) { |
64 | | - const items = grouped.get(kind) |
65 | | - if (!items || items.length === 0) continue |
66 | | - |
67 | | - const section = KIND_HEADERS[kind] |
68 | | - const sectionHeader = `\n### ${section.header}\n_${section.instruction}_\n` |
69 | | - if (used + sectionHeader.length > budget) break |
70 | | - result += sectionHeader |
71 | | - used += sectionHeader.length |
72 | | - |
73 | | - // Sort by applied count descending so most-used entries get priority in budget |
74 | | - const sorted = [...items].sort((a, b) => b.meta.applied - a.meta.applied) |
75 | | - for (const entry of sorted) { |
76 | | - const formatted = formatEntry(entry) |
77 | | - const needed = formatted.length + 2 |
78 | | - if (used + needed > budget) break |
79 | | - result += "\n" + formatted + "\n" |
80 | | - used += needed |
81 | | - injected.push(entry) |
82 | | - } |
83 | | - } |
84 | | - |
85 | | - // Increment applied count once per session per entry (fire-and-forget) |
86 | | - for (const entry of injected) { |
87 | | - if (!appliedThisSession.has(entry.id)) { |
88 | | - appliedThisSession.add(entry.id) |
89 | | - TrainingStore.incrementApplied(entry.scope, entry.kind, entry.name).catch(() => {}) |
90 | | - } |
91 | | - } |
92 | | - |
93 | | - return result |
| 21 | + return MemoryPrompt.injectTrainingOnly(budget) |
94 | 22 | } |
95 | 23 |
|
96 | 24 | export async function budgetUsage(budget: number = TRAINING_BUDGET): Promise<{ |
|
0 commit comments