release: v2.0.8 - UX Persistence & Per-Agent Knowledge Mix (2026-05-14)
This commit is contained in:
@@ -32,9 +32,15 @@
|
||||
*/
|
||||
import * as vscode from 'vscode';
|
||||
import { IAIService } from '../../core/services';
|
||||
import { logError, logInfo } from '../../utils';
|
||||
import { getActiveBrainProfile, logError, logInfo } from '../../utils';
|
||||
import { retrieveScoped, buildContextBlock } from '../../skills/scopedBrainRetriever';
|
||||
import { resolveScopeForAgent } from '../../skills/agentKnowledgeMap';
|
||||
import {
|
||||
mapWeightToBrainFileLimit,
|
||||
buildKnowledgeMixPolicy,
|
||||
} from '../../retrieval/knowledgeMix';
|
||||
import { getCompanyAgent } from './agents';
|
||||
import { modelForAgent, readCompanyState } from './companyConfig';
|
||||
import { modelForAgent, readCompanyState, resolveCompanyKnowledgeMix } from './companyConfig';
|
||||
import { runCeoPlanner } from './ceoPlanner';
|
||||
import { runCeoReporter } from './ceoReporter';
|
||||
import { buildSpecialistPrompt } from './promptBuilder';
|
||||
@@ -86,6 +92,18 @@ export interface DispatcherDeps {
|
||||
ai: IAIService;
|
||||
/** Default model to fall back to when an agent has no override. */
|
||||
defaultModel: string;
|
||||
/**
|
||||
* Global Knowledge Mix weight (0–100) — fallback when an agent has no
|
||||
* per-agent override. Mirrors `g1nation.knowledgeMix.secondBrainWeight`.
|
||||
*/
|
||||
globalKnowledgeMixWeight: number;
|
||||
/**
|
||||
* Baseline number of brain files to retrieve at weight=50 (balanced).
|
||||
* The actual count is `mapWeightToBrainFileLimit(weight, baseline)`.
|
||||
* Pass the same value the chat path uses (`config.memoryLongTermFiles`)
|
||||
* so company-mode behaviour stays in sync.
|
||||
*/
|
||||
brainFileBaseline?: number;
|
||||
/**
|
||||
* Apply ConnectAI's action-tag executor to the specialist's raw response.
|
||||
* Without this hook, agent outputs containing `<create_file>` etc. would
|
||||
@@ -266,10 +284,52 @@ async function _dispatchOne(
|
||||
};
|
||||
});
|
||||
|
||||
// ── Second Brain RAG for this specialist ────────────────────────────────
|
||||
// The non-company chat path uses `AgentExecutor.buildMemoryContext` to
|
||||
// pull RAG chunks before every LLM call. The dispatcher used to skip
|
||||
// that entirely, leaving company agents *blind* to the user's stored
|
||||
// knowledge — which made the Knowledge Mix slider effectively a no-op
|
||||
// for company turns. We now run a lightweight scoped retrieval here so
|
||||
// every dispatch sees the same brain the user expects, weighted by the
|
||||
// agent's own Knowledge Mix.
|
||||
const { weight: knowledgeWeight, source: knowledgeMixSource } =
|
||||
resolveCompanyKnowledgeMix(state, agentId, deps.globalKnowledgeMixWeight);
|
||||
const brainFileLimit = mapWeightToBrainFileLimit(knowledgeWeight, deps.brainFileBaseline ?? 6);
|
||||
let brainContext = '';
|
||||
if (brainFileLimit > 0) {
|
||||
try {
|
||||
const brain = getActiveBrainProfile();
|
||||
const brainRoot = brain?.localBrainPath || '';
|
||||
if (brainRoot) {
|
||||
// Reuse the agent ↔ knowledge map: if the same agent name
|
||||
// appears there (free-form .md path or canonical id), we
|
||||
// honour its `knowledgeFolders` scope. Otherwise we search
|
||||
// the whole brain so a missing mapping doesn't starve the
|
||||
// dispatcher.
|
||||
const scope = resolveScopeForAgent(agentId, brainRoot);
|
||||
const retrieval = retrieveScoped(task, brainRoot, scope.folders, {
|
||||
maxResults: brainFileLimit,
|
||||
});
|
||||
brainContext = buildContextBlock(retrieval);
|
||||
}
|
||||
} catch (e: any) {
|
||||
logError('company.dispatcher: RAG retrieval failed; continuing without brain context.', {
|
||||
agentId, error: e?.message ?? String(e),
|
||||
});
|
||||
}
|
||||
}
|
||||
const policyBlock = buildKnowledgeMixPolicy({
|
||||
weight: knowledgeWeight,
|
||||
source: knowledgeMixSource,
|
||||
agent: def.name,
|
||||
});
|
||||
|
||||
const system = buildSpecialistPrompt({
|
||||
agentId, state,
|
||||
agentMemory: memory, sharedDecisions: decisions,
|
||||
peerOutputs,
|
||||
brainContext, // injected as `[SECOND BRAIN CONTEXT]` block
|
||||
knowledgeMixPolicy: policyBlock, // injected as `[KNOWLEDGE MIX POLICY]` block
|
||||
});
|
||||
const model = modelForAgent(state, agentId, deps.defaultModel);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user