Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 11 additions & 8 deletions packages/agent-core-v2/docs/di-scope-domains.puml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ package "Agent scope (per agent)" #FDF5E6 {
rectangle "<b>record</b>\n<size:9><i>Agent</i></size>\n IAgentRecordService" as record #FDEBD0
rectangle "<b>blobStore</b>\n<size:9><i>Agent</i></size>\n IAgentBlobStoreService" as blobStore #FDEBD0
rectangle "<b>contextMemory</b>\n<size:9><i>Agent</i></size>\n IAgentContextMemoryService" as contextMemory #FDEBD0
rectangle "<b>contextOps</b>\n<size:9><i>Agent</i></size>\n IAgentContextOpsService" as contextOps #FDEBD0
rectangle "<b>contextProjector</b>\n<size:9><i>Agent</i></size>\n IAgentContextProjectorService" as contextProjector #FDEBD0
rectangle "<b>contextInjector</b>\n<size:9><i>Agent</i></size>\n IAgentContextInjectorService" as contextInjector #FDEBD0
rectangle "<b>contextSize</b>\n<size:9><i>Agent</i></size>\n IAgentContextSizeService" as contextSize #FDEBD0
rectangle "<b>systemReminder</b>\n<size:9><i>Agent</i></size>\n IAgentSystemReminderService" as systemReminder #FDEBD0
rectangle "<b>profile</b>\n<size:9><i>Agent</i></size>\n IAgentProfileService" as profile #FDEBD0
rectangle "<b>prompt</b>\n<size:9><i>Agent</i></size>\n IAgentPromptService" as prompt #FDEBD0
rectangle "<b>turn</b>\n<size:9><i>Agent</i></size>\n IAgentTurnService" as turn #FDEBD0
Expand Down Expand Up @@ -164,14 +164,14 @@ filestore --> storage #34495E
record --> wireRecord #34495E
contextMemory --> wireRecord #34495E
contextMemory --> record #34495E
contextOps --> contextMemory #34495E
contextInjector --> contextMemory #34495E
contextInjector --> contextOps #34495E
contextInjector --> turn #34495E
contextInjector --> loop #34495E
contextInjector --> systemReminder #34495E
contextSize --> contextMemory #34495E
contextSize --> record #34495E
contextSize --> wireRecord #34495E
systemReminder --> contextMemory #34495E
profile --> wireRecord #34495E
profile --> record #34495E
profile --> record #34495E
Expand All @@ -180,6 +180,7 @@ profile --> config #34495E
profile --> modelProvider #34495E
profile --> chatProvider #34495E
prompt --> contextMemory #34495E
prompt --> contextOps #34495E
prompt --> turn #34495E
prompt --> loop #34495E
prompt --> wireRecord #34495E
Expand All @@ -188,8 +189,9 @@ turn --> loop #34495E
turn --> record #34495E
turn --> wireRecord #34495E
turn --> contextMemory #34495E
turn --> contextOps #34495E
turn --> telemetry #34495E
loop --> contextMemory #34495E
loop --> contextOps #34495E
loop --> contextSize #34495E
loop --> llmRequester #34495E
loop --> record #34495E
Expand Down Expand Up @@ -237,11 +239,11 @@ plan --> contextInjector #34495E
plan --> telemetry #34495E
goal --> wireRecord #34495E
goal --> record #34495E
goal --> systemReminder #34495E
goal --> record #34495E
goal --> telemetry #34495E
goal --> contextInjector #34495E
goal --> contextMemory #34495E
goal --> contextOps #34495E
goal --> turn #34495E
goal --> loop #34495E
goal --> toolRegistry #34495E
Expand All @@ -263,6 +265,7 @@ task --> wireRecord #34495E
task --> telemetry #34495E
task --> prompt #34495E
task --> contextMemory #34495E
task --> contextOps #34495E
task --> config #34495E
task --> storage #34495E
task --> session_context #34495E
Expand All @@ -276,7 +279,8 @@ cron --> config #34495E
cron --> storage #34495E
swarm --> wireRecord #34495E
swarm --> record #34495E
swarm --> systemReminder #34495E
swarm --> contextMemory #34495E
swarm --> contextOps #34495E
mcp --> toolRegistry #34495E
mcp --> record #34495E
mcp --> toolExecutor #34495E
Expand Down Expand Up @@ -348,7 +352,7 @@ flag ..> config #16A085 : onDidChangeConfiguration
permissionMode ..> wireRecord #16A085 : permission.set_mode
userTool ..> wireRecord #16A085 : tools.register_/unregister_user_tool
profile ..> wireRecord #16A085 : config.update / tools.set_active_tools
contextMemory ..> wireRecord #16A085 : context.splice
contextMemory ..> wireRecord #16A085 : context.<type> ops
cron ..> wireRecord #16A085 : cron.add / delete / cursor
todo ..> wireRecord #16A085 : todo.set
fullCompaction ..> wireRecord #16A085 : full_compaction.begin/cancel/complete
Expand All @@ -375,7 +379,6 @@ toolStore ..> wireRecord #16A085 : tools.update_store
usage ..> wireRecord #16A085 : usage.record
contextSize ..> contextMemory #16A085 : hooks.onSpliced
contextSize ..> wireRecord #16A085 : context_size.measured
loop ..> contextMemory #16A085 : hooks.onSpliced
loop ..> wireRecord #16A085 : hooks.onResumeEnded
plan ..> wireRecord #16A085 : plan_mode.enter/cancel/exit

Expand Down
2 changes: 1 addition & 1 deletion packages/agent-core-v2/docs/di-scope-domains.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 4 additions & 5 deletions packages/agent-core-v2/scripts/check-domain-layers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ const DOMAIN_LAYER = new Map([
['usage', 4],
['toolDedupe', 4],
['contextMemory', 4],
['contextOps', 4],
['contextInjector', 4],
['systemReminder', 4],
['contextProjector', 4],
['contextSize', 4],
['fullCompaction', 4],
Expand Down Expand Up @@ -297,10 +297,6 @@ const ALLOWED_EXCEPTIONS = new Set([
'permissionPolicy>profile',
'permissionRules>replayBuilder',
'record>replayBuilder',
// `record` owns the replay read model, whose `message` records carry
// `ContextMessage` (L4). `removeLastMessages` takes a set of them, so the
// projection side references the context message type by structure only.
'record>contextMemory',
'plugin>externalHooks',
'plugin>mcp',
'profile>session',
Expand All @@ -314,6 +310,9 @@ const ALLOWED_EXCEPTIONS = new Set([
'toolExecutor>loop',
'userTool>profile',
'wireRecord>contextMemory',
// The v1.5 migration emits `context.*` operation records and references the
// arg tuple types declared by their owning domains (L4) — type-only.
'wireRecord>contextOps',
'wireRecord>loop',
'wireRecord>tool',
'hostFolderBrowser>os/backends',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ function sameRef(a: EdgeRef, b: EdgeRef): boolean {
/**
* Collect every top-level `interface` declaration in the tree, keyed by
* name. Used to pull each service's public callable surface out of its
* token interface (e.g. `interface IAgentSystemReminderService { ... }`)
* token interface (e.g. `interface IAgentContextOpsService { ... }`)
* so the graph view can render every method as a port row even when
* nothing calls into it yet.
*
Expand Down
6 changes: 3 additions & 3 deletions packages/agent-core-v2/scripts/dep-graph/analyzer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ export interface ServiceNode {
* bound at App and Session).
*/
id: string;
/** Token identifier (e.g. `IAgentSystemReminderService`). */
/** Token identifier (e.g. `IAgentContextOpsService`). */
token: string;
/** Impl class name (e.g. `AgentSystemReminderService`). */
/** Impl class name (e.g. `AgentContextOpsService`). */
impl: string;
scope: ServiceScope;
/** First folder under `src/` (e.g. `systemReminder`). */
/** First folder under `src/` (e.g. `contextOps`). */
domain: string;
/** Repo-relative path of the impl file. */
file: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
import { InstantiationType } from '#/_base/di/extensions';
import { LifecycleScope, registerScopedService } from '#/_base/di/scope';

import { IAgentContextOpsService } from '#/agent/contextOps';
import { IAgentContextMemoryService } from '#/agent/contextMemory';
import { IAgentLoopService } from '#/agent/loop';
import { IAgentSystemReminderService } from '#/agent/systemReminder';
import { IAgentTurnService } from '#/agent/turn';
import type { ContextMessage } from '#/agent/contextMemory';
import {
Expand All @@ -33,7 +33,7 @@ export class AgentContextInjectorService extends Disposable implements IAgentCon
@IAgentContextMemoryService private readonly context: IAgentContextMemoryService,
@IAgentTurnService turnService: IAgentTurnService,
@IAgentLoopService loopService: IAgentLoopService,
@IAgentSystemReminderService private readonly reminders: IAgentSystemReminderService,
@IAgentContextOpsService private readonly contextOps: IAgentContextOpsService,
) {
super();
this._register(
Expand Down Expand Up @@ -89,7 +89,7 @@ export class AgentContextInjectorService extends Disposable implements IAgentCon
});
if (!this.entries.has(entry)) continue;
if (content === undefined || content.trim().length === 0) continue;
this.reminders.appendSystemReminder(content, {
this.contextOps.appendSystemReminder(content, {
kind: 'injection',
variant: entry.variant,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ import { InstantiationType } from '#/_base/di/extensions';
import { LifecycleScope, registerScopedService } from '#/_base/di/scope';
import { escapeXmlAttr } from '#/_base/utils/xml-escape';
import { IAgentContextMemoryService } from '#/agent/contextMemory';
import { IAgentContextOpsService } from '#/agent/contextOps';
import { ILogService } from '#/app/log';
import { IPluginService } from '#/app/plugin';
import type { EnabledPluginSessionStart } from '#/app/plugin/types';
import { ISessionSkillCatalog } from '#/session/sessionSkillCatalog';
import type { SkillCatalog, SkillDefinition } from '#/app/globalSkillCatalog/types';
import { IAgentSystemReminderService } from '#/agent/systemReminder';

import { IAgentContextInjectorService } from './contextInjector';

Expand All @@ -43,7 +43,7 @@ export class PluginSessionStartInjectorService

constructor(
@IAgentContextInjectorService private readonly injector: IAgentContextInjectorService,
@IAgentSystemReminderService private readonly reminders: IAgentSystemReminderService,
@IAgentContextOpsService private readonly contextOps: IAgentContextOpsService,
@IAgentContextMemoryService private readonly context: IAgentContextMemoryService,
@IPluginService private readonly plugins: IPluginService,
@ISessionSkillCatalog private readonly skillCatalog: ISessionSkillCatalog,
Expand Down Expand Up @@ -80,12 +80,12 @@ export class PluginSessionStartInjectorService
log: this.log,
});
if (reminder !== undefined) {
this.reminders.appendSystemReminder(
this.contextOps.appendSystemReminder(
`${reminder}\n\nThis supersedes any earlier plugin_session_start reminder in this session.`,
{ kind: 'injection', variant: INJECTION_VARIANT },
);
} else if (shouldNeutralizePluginSessionStart(this.context.get())) {
this.reminders.appendSystemReminder(
this.contextOps.appendSystemReminder(
'There are currently no active plugin session starts. ' +
'This supersedes any earlier plugin_session_start reminder in this session.',
{ kind: 'injection', variant: INJECTION_VARIANT },
Expand Down
53 changes: 41 additions & 12 deletions packages/agent-core-v2/src/agent/contextMemory/contextMemory.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
import { createDecorator } from "#/_base/di";
import type { ContentPart } from '#/app/llmProtocol';

import type { Hooks } from '#/hooks';
import type { AgentReplayRecordPayload } from '#/agent/replayBuilder/types';
import type { ContextMessage } from './types';

export interface ContextSplicedEvent {
start: number;
deleteCount: number;
messages: ContextMessage[];
tokens?: number;
}

export type ContextSplice = (
start: number,
deleteCount: number,
insert: readonly ContextMessage[],
tokens?: number,
) => void;

export interface ContextReplayWriter {
push(record: AgentReplayRecordPayload): void;
removeMessages(messageIds: ReadonlySet<string>): void;
cut(): void;
}

export interface ContextOperationBlobTarget<T extends readonly unknown[]> {
readonly parts: readonly ContentPart[];
replace(args: T, parts: readonly ContentPart[]): T;
}

export interface ContextOperationDefinition<T extends readonly unknown[]> {
readonly type: string;
readonly apply: (splice: ContextSplice, ...args: T) => void;
readonly replay: (replay: ContextReplayWriter, ...args: T) => void;
readonly blobs?: (args: T) => Iterable<ContextOperationBlobTarget<T>>;
}

export type ContextOperation<T extends readonly unknown[]> = (...args: T) => void;

export interface IAgentContextMemoryService {
readonly _serviceBrand: undefined;

defineOperation<T extends readonly unknown[]>(
definition: ContextOperationDefinition<T>,
): ContextOperation<T>;

get(): readonly ContextMessage[];
splice(
start: number,
deleteCount: number,
messages: readonly ContextMessage[],
tokens?: number,
): void;

readonly hooks: Hooks<{
onSpliced: {
start: number;
deleteCount: number;
messages: ContextMessage[];
tokens?: number;
};
onSpliced: ContextSplicedEvent;
}>;
}

Expand Down
Loading
Loading