Skip to content
Closed
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4a89fd7
feat: add experience system (Phase 1–2) to capture curation signals
ngduyanhece Mar 17, 2026
dd55a41
fix: harden experience system Phase 3 scoring correctness and persist…
ngduyanhece Mar 17, 2026
2e600c1
feat: add Phase 4 experience consolidation service
ngduyanhece Mar 17, 2026
2df4a0b
fix: rename IConsolidationLlm.generate systemPrompt param to instruct…
ngduyanhece Mar 17, 2026
d88c47d
fix: prune static queue map entry after queue drains
ngduyanhece Mar 17, 2026
3a4434b
fix: correct consolidation semantics and OOD detection
ngduyanhece Mar 17, 2026
8df9da9
fix: harden experience pipeline against partial failures and edge cases
ngduyanhece Mar 17, 2026
ffadfbd
Merge pull request #796 from campfirein/feat/ENG-1537
ngduyanhece Mar 17, 2026
c4b90a0
feat: add autocontext-inspired context improvement patterns
ngduyanhece Mar 17, 2026
a832351
fix: resolve review issues in compression evaluator, progress contrib…
ngduyanhece Mar 18, 2026
18db3d1
fix: detach session progress tracker on dispose and document naive br…
ngduyanhece Mar 18, 2026
c41cc02
fix: prevent compressionCount double-increment and correct attach() doc
ngduyanhece Mar 18, 2026
a9a0915
fix: salvage valid strings from mixed LLM arrays in bullet parser
ngduyanhece Mar 18, 2026
532248d
Merge remote-tracking branch 'origin/proj/experence-domain' into feat…
ngduyanhece Mar 18, 2026
9fd3f2b
Merge pull request #802 from campfirein/feat/ENG-1537
ngduyanhece Mar 18, 2026
10aa128
feat: auto-export accumulated experience into agent SKILL.md files
ngduyanhece Mar 18, 2026
99016f1
feat: auto-export accumulated experience into agent SKILL.md files
ngduyanhece Mar 18, 2026
6a1dcc2
refactor: use options object for ExperienceHookService constructor an…
ngduyanhece Mar 18, 2026
0c1daff
fix: propagate non-ENOENT errors and isolate skill export queue
ngduyanhece Mar 18, 2026
7109007
Merge remote-tracking branch 'origin/proj/experence-domain' into feat…
ngduyanhece Mar 18, 2026
2a96719
feat: add brv connectors sync command and remove brv-export-skill MCP…
ngduyanhece Mar 19, 2026
e6633cf
fix: tighten sync command, coordinator return type, and hook fail-open
ngduyanhece Mar 19, 2026
17699ff
Merge pull request #803 from campfirein/feat/ENG-1556
ngduyanhece Mar 19, 2026
bb3ed2a
refactor: extract SkillExportResult and SkillBuildAndSyncResult into …
ngduyanhece Mar 19, 2026
071b249
refactor: use SkillExportScope in SkillExportTarget and re-export it
ngduyanhece Mar 19, 2026
7bcfbdc
refactor: import skill export result from shared types
ngduyanhece Mar 19, 2026
33835cc
Merge remote-tracking branch 'origin/proj/experence-domain' into feat…
ngduyanhece Mar 19, 2026
f5bc923
Merge pull request #809 from campfirein/feat/ENG-1556
ngduyanhece Mar 19, 2026
f6606ca
Merge proj/ov-pattern into proj/experence-domain with conflict resolu…
ngduyanhece Mar 30, 2026
1bb4a4f
feat: refactor experience domain to entry-based storage with native p…
ngduyanhece Mar 30, 2026
9f4353e
Fix synthesis reflection overwrite path
ngduyanhece Mar 30, 2026
19dfcb5
Document daily synthesis retention
ngduyanhece Mar 30, 2026
156e569
Resolve remaining experience review comments
ngduyanhece Mar 30, 2026
ed16ee8
Address final PR review blockers
ngduyanhece Mar 30, 2026
ec018b1
chore: remove migration code, connectors sync, and add E2E tests
ngduyanhece Mar 30, 2026
efdc022
Resolve remaining PR review blockers
ngduyanhece Mar 30, 2026
345f22a
Merge pull request #894 from campfirein/feat/ENG-1746
ngduyanhece Mar 30, 2026
ff7f4f1
feat: implement memory-performance correlation (Phase 2)
ngduyanhece Mar 31, 2026
a74d0f0
Address PR review feedback on search correlation
ngduyanhece Mar 31, 2026
dbbcee1
Address remaining PR review threads
ngduyanhece Mar 31, 2026
3aa4745
fix: address PR review comments
ngduyanhece Apr 3, 2026
3a58d5f
feat: [ENG-1917] add Star History chart section to README.
leehpham Apr 4, 2026
52a2a67
Merge pull request #309 from campfirein/feat/ENG-1917
leehpham Apr 4, 2026
6598f63
feat: [ENG-1910] add ByteRover Cloud section to README.
leehpham Apr 4, 2026
c6dbfa9
Merge pull request #310 from campfirein/feat/ENG-1910
leehpham Apr 4, 2026
660a115
Merge remote-tracking branch 'origin/main' into feat/ENG-1753
ngduyanhece Apr 4, 2026
5a137ea
fix: address PR review round 2 — import style, score boundary, commen…
ngduyanhece Apr 4, 2026
eeee720
fix: address latest PR review feedback
ngduyanhece Apr 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/agent/core/domain/agent-events/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const AGENT_EVENT_NAMES = [
*/
export const SESSION_EVENT_NAMES = [
'llmservice:chunk',
'llmservice:compressionQuality',
'llmservice:contextCompressed',
'llmservice:contextOverflow',
'llmservice:contextPruned',
Expand Down Expand Up @@ -230,6 +231,20 @@ export interface AgentEventMap {
type: 'reasoning' | 'text'
}

/**
* Emitted after the full compression pipeline completes, reporting quality dimensions
* of the final compressed output (Pattern 4). Forwarded from SessionEventMap with sessionId.
*/
'llmservice:compressionQuality': {
dimensions: {
factualCompleteness: number
toolContextPreservation: number
userIntentClarity: number
}
overallScore: number
sessionId: string
}

/**
* Emitted when conversation context is compressed via summarization.
* @property {number} compressedTokens - Token count after compression
Expand Down Expand Up @@ -592,6 +607,21 @@ export interface SessionEventMap {
type: 'reasoning' | 'text'
}

/**
* Emitted after the full compression pipeline completes, reporting quality dimensions
* of the final compressed output (Pattern 4).
* @property {object} dimensions - Per-dimension quality scores (0-1)
* @property {number} overallScore - Weighted overall quality score (0-1)
*/
'llmservice:compressionQuality': {
dimensions: {
factualCompleteness: number
toolContextPreservation: number
userIntentClarity: number
}
overallScore: number
}

/**
* Emitted when conversation context is compressed via summarization.
* @property {number} compressedTokens - Token count after compression
Expand Down
1 change: 1 addition & 0 deletions src/agent/core/interfaces/cipher-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export interface CipherAgentServices {
* - LLMService: LLM client with isolated context manager
*/
export interface SessionServices {
cleanup?: () => void
llmService: ILLMService
sessionEventBus: SessionEventBus
}
Expand Down
9 changes: 9 additions & 0 deletions src/agent/core/interfaces/i-sandbox-service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { SessionInsightsTracker } from '../../../server/infra/context-tree/session-insights-tracker.js'
import type { ISearchKnowledgeService } from '../../infra/sandbox/tools-sdk.js'
import type { SessionManager } from '../../infra/session/session-manager.js'
import type { EnvironmentContext } from '../domain/environment/types.js'
Expand Down Expand Up @@ -74,6 +75,14 @@ export interface ISandboxService {
*/
setFileSystem?(fileSystem: IFileSystem): void

/**
* Set the session insights tracker for performance correlation.
* When set, ToolsSDK.searchKnowledge() records surfaced paths per session.
*
* @param tracker - Session insights tracker instance
*/
setInsightsTracker?(tracker: SessionInsightsTracker): void

/**
* Set a variable in a session's sandbox.
* If the sandbox doesn't exist yet, the variable is buffered and injected
Expand Down
9 changes: 9 additions & 0 deletions src/agent/infra/agent/cipher-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,15 @@ export class CipherAgent extends BaseAgent implements ICipherAgent {
}
}

/**
* Set the session insights tracker for performance-memory correlation.
* Forwarded to sandboxService so ToolsSDK.searchKnowledge() records surfaced paths.
*/
public setInsightsTracker(tracker: import('../../../server/infra/context-tree/session-insights-tracker.js').SessionInsightsTracker): void {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (import style): Same inline dynamic import(...) type pattern that was flagged and fixed in tools-sdk.ts in the previous round — now it's reintroduced here. Consider lifting it to a top-level import to keep the file consistent with the rest of the imports:

Suggested change
public setInsightsTracker(tracker: import('../../../server/infra/context-tree/session-insights-tracker.js').SessionInsightsTracker): void {
public setInsightsTracker(tracker: SessionInsightsTracker): void {

And add at the top of the file alongside other import type declarations:

import type { SessionInsightsTracker } from '../../../server/infra/context-tree/session-insights-tracker.js'

this.ensureStarted()
this.services!.sandboxService.setInsightsTracker?.(tracker)
}

/**
* Set a variable in the agent's default session sandbox.
*/
Expand Down
27 changes: 27 additions & 0 deletions src/agent/infra/agent/service-initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import { AgentEventBus, SessionEventBus } from '../events/event-emitter.js'
import { FileSystemService } from '../file-system/file-system-service.js'
import { AgentLLMService } from '../llm/agent-llm-service.js'
import { CompactionService } from '../llm/context/compaction/compaction-service.js'
import { CompressionQualityEvaluator } from '../llm/context/compression/compression-quality-evaluator.js'
import { EscalatedCompressionStrategy } from '../llm/context/compression/escalated-compression.js'
import { MiddleRemovalStrategy } from '../llm/context/compression/middle-removal.js'
import { OldestRemovalStrategy } from '../llm/context/compression/oldest-removal.js'
import { SessionProgressTracker } from '../llm/context/session-progress-tracker.js'
import {
LoggingContentGenerator,
RetryableContentGenerator,
Expand All @@ -44,6 +46,8 @@ import { GranularHistoryStorage } from '../storage/granular-history-storage.js'
import { MessageStorageService } from '../storage/message-storage-service.js'
import { ContextTreeStructureContributor } from '../system-prompt/contributors/context-tree-structure-contributor.js'
import { MapSelectionContributor } from '../system-prompt/contributors/map-selection-contributor.js'
import { PerformanceTrendContributor } from '../system-prompt/contributors/performance-trend-contributor.js'
import { ProgressTrajectoryContributor } from '../system-prompt/contributors/progress-trajectory-contributor.js'
import { SystemPromptManager } from '../system-prompt/system-prompt-manager.js'
import { CoreToolScheduler } from '../tools/core-tool-scheduler.js'
import { DEFAULT_POLICY_RULES } from '../tools/default-policy-rules.js'
Expand Down Expand Up @@ -208,6 +212,13 @@ export async function createCipherAgentServices(
const mapSelectionContributor = new MapSelectionContributor('mapSelection', 16)
systemPromptManager.registerContributor(mapSelectionContributor)

// Register performance trend contributor for curate/query commands
// Priority 17 — after map selection, before memories
const performanceTrendContributor = new PerformanceTrendContributor('performanceTrend', 17, {
workingDirectory,
})
systemPromptManager.registerContributor(performanceTrendContributor)

// 7. Abstract generation queue (generator injected later via rebindCurateTools)
const abstractQueue = new AbstractGenerationQueue(workingDirectory)

Expand Down Expand Up @@ -310,6 +321,10 @@ export function createSessionServices(
// 1. Create session-specific event bus
const sessionEventBus = new SessionEventBus()

// 1b. Create session progress tracker (Pattern 1: Progress Trajectory)
const progressTracker = new SessionProgressTracker(sessionEventBus)
progressTracker.attach()

// 2. Create session-scoped logger
const sessionLogger = new EventBasedLogger(sharedServices.agentEventBus, 'LLMService', sessionId)

Expand Down Expand Up @@ -350,6 +365,12 @@ export function createSessionServices(
model: llmConfig.model ?? 'gemini-3-flash-preview',
})

// Per-session progress contributor (Pattern 1)
const progressContributor = new ProgressTrajectoryContributor('progress', 25, progressTracker)

// Pattern 4: compression quality evaluator (final-output evaluation after full chain)
const compressionQualityEvaluator = new CompressionQualityEvaluator({warningThreshold: 0.5})

return new AgentLLMService(
sessionId,
generator,
Expand All @@ -364,6 +385,7 @@ export function createSessionServices(
},
{
compactionService: sharedServices.compactionService,
compressionQualityEvaluator,
compressionStrategies: [
escalatedStrategy,
new MiddleRemovalStrategy({preserveEnd: 5, preserveStart: 4}),
Expand All @@ -372,7 +394,9 @@ export function createSessionServices(
historyStorage: sharedServices.historyStorage,
logger: sessionLogger,
memoryManager: sharedServices.memoryManager,
progressTracker,
sandboxService: sharedServices.sandboxService,
sessionContributors: [progressContributor],
sessionEventBus,
systemPromptManager: sharedServices.systemPromptManager,
toolManager: sharedServices.toolManager,
Expand Down Expand Up @@ -401,6 +425,9 @@ export function createSessionServices(
// to ensure proper cleanup when sessions are disposed

return {
cleanup() {
progressTracker.detach()
},
llmService,
sessionEventBus,
}
Expand Down
37 changes: 36 additions & 1 deletion src/agent/infra/llm/agent-llm-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {MessageParam} from '@anthropic-ai/sdk/resources/messages'
import type {Content} from '@google/genai'
import type {ChatCompletionMessageParam} from 'openai/resources/chat/completions'

import type {SystemPromptContributor} from '../../core/domain/system-prompt/types.js'
import type {ToolExecutionResult} from '../../core/domain/tools/tool-error.js'
import type {ToolSet} from '../../core/domain/tools/types.js'
import type {ExecutionContext} from '../../core/interfaces/i-cipher-agent.js'
Expand All @@ -22,7 +23,9 @@ import type {MemoryManager} from '../memory/memory-manager.js'
import type {SystemPromptManager} from '../system-prompt/system-prompt-manager.js'
import type {ToolManager} from '../tools/tool-manager.js'
import type {CompactionService} from './context/compaction/compaction-service.js'
import type {CompressionQualityEvaluator} from './context/compression/compression-quality-evaluator.js'
import type {ICompressionStrategy} from './context/compression/types.js'
import type {SessionProgressTracker} from './context/session-progress-tracker.js'

import {getErrorMessage} from '../../../server/utils/error-helpers.js'
import {AgentStateMachine} from '../../core/domain/agent/agent-state-machine.js'
Expand Down Expand Up @@ -173,10 +176,14 @@ export class AgentLLMService implements ILLMService {
private readonly metadataHandler: ToolMetadataHandler
private readonly mutex = new AsyncMutex()
private readonly outputProcessor: ToolOutputProcessor
/** Optional progress tracker for recording iteration completions (Pattern 1). */
private readonly progressTracker?: SessionProgressTracker
private readonly providerId: string
private readonly providerType: 'claude' | 'gemini' | 'openai'
/** Optional sandbox service for rolling checkpoint variable injection (Pattern 1) */
/** Optional sandbox service for rolling checkpoint variable injection */
private readonly sandboxService?: ISandboxService
/** Per-session system prompt contributors (appended after shared SystemPromptManager output). */
private readonly sessionContributors: SystemPromptContributor[]
private readonly sessionEventBus: SessionEventBus
private readonly sessionId: string
private readonly systemPromptManager: SystemPromptManager
Expand Down Expand Up @@ -215,13 +222,19 @@ export class AgentLLMService implements ILLMService {
config: AgentLLMServiceConfig,
options: {
compactionService?: CompactionService
/** Optional quality evaluator for measuring compression output (Pattern 4). */
compressionQualityEvaluator?: CompressionQualityEvaluator
/** Optional compression strategies for context overflow management */
compressionStrategies?: ICompressionStrategy[]
historyStorage?: IHistoryStorage
logger?: ILogger
memoryManager?: MemoryManager
/** Optional progress tracker for recording iteration completions (Pattern 1). */
progressTracker?: SessionProgressTracker
/** Optional sandbox service for rolling checkpoint variable injection */
sandboxService?: ISandboxService
/** Per-session system prompt contributors (appended after shared prompt). */
sessionContributors?: SystemPromptContributor[]
sessionEventBus: SessionEventBus
systemPromptManager: SystemPromptManager
toolManager: ToolManager
Expand All @@ -230,7 +243,9 @@ export class AgentLLMService implements ILLMService {
this.sessionId = sessionId
this.generator = generator
this.compactionService = options.compactionService
this.progressTracker = options.progressTracker
this.sandboxService = options.sandboxService
this.sessionContributors = options.sessionContributors ?? []
this.toolManager = options.toolManager
this.systemPromptManager = options.systemPromptManager
this.memoryManager = options.memoryManager
Expand Down Expand Up @@ -281,10 +296,13 @@ export class AgentLLMService implements ILLMService {

// Initialize context manager with optional history storage
this.contextManager = new ContextManager({
compressionQualityEvaluator: options.compressionQualityEvaluator,
compressionStrategies: options.compressionStrategies,
formatter: this.formatter,
historyStorage: options.historyStorage,
logger: this.logger,
maxInputTokens: this.config.maxInputTokens,
sessionEventBus: options.sessionEventBus,
sessionId,
tokenizer: this.tokenizer,
})
Expand Down Expand Up @@ -370,9 +388,13 @@ export class AgentLLMService implements ILLMService {
tools: toolSet,
})

// Record completed iteration before result check so one-turn tasks are counted
this.progressTracker?.recordIteration()

if (result !== null) {
// Task complete - no tool calls
stateMachine.complete()

return result
}

Expand Down Expand Up @@ -921,6 +943,19 @@ export class AgentLLMService implements ILLMService {
systemPrompt = systemPrompt + '\n\n' + reflectionPrompt
}

// Append per-session contributor content (never cached — changes every iteration)
for (const contributor of this.sessionContributors) {
// eslint-disable-next-line no-await-in-loop -- Sequential to maintain deterministic prompt ordering
const content = await contributor.getContent({
availableMarkers,
availableTools,
commandType: executionContext?.commandType,
})
if (content) {
systemPrompt = systemPrompt + '\n\n' + content
}
}

// Verbose debug: Show complete system prompt
if (this.config.verbose) {
this.logger.debug('System prompt details', {
Expand Down
Loading
Loading