mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-23 18:01:13 +00:00
* refactor(deadcode): trim auto-reply and CLI exports * refactor(deadcode): trim cron and task exports * refactor(deadcode): trim fleet and process exports * test(deadcode): exercise live task and process seams * test(fleet): cover stream redaction through owner module * refactor(security): trim dead internal exports * refactor(secrets): trim dead internal exports * refactor(deadcode): trim remaining src exports * refactor(deadcode): remove test-only runtime exports * refactor(deadcode): trim pairing test exports * refactor(deadcode): reconcile refreshed baseline * test(auto-reply): deduplicate queue state imports
524 lines
18 KiB
TypeScript
524 lines
18 KiB
TypeScript
// Context-engine public types define the pluggable context-management lifecycle.
|
|
import type { AgentMessage } from "../agents/runtime/index.js";
|
|
import type { MemoryCitationsMode } from "../config/types.memory.js";
|
|
|
|
// Result types
|
|
|
|
export type AssembleResult = {
|
|
/** Ordered messages to use as model context */
|
|
messages: AgentMessage[];
|
|
/** Estimated total tokens in assembled context */
|
|
estimatedTokens: number;
|
|
/**
|
|
* Controls which token estimate the runner treats as authoritative for
|
|
* preemptive overflow prechecks. The returned `messages` are always the
|
|
* prompt sent to the model; this only affects the precheck's token comparison.
|
|
*
|
|
* - "assembled": the generic precheck uses only the assembled prompt's estimate
|
|
* unless the engine owns compaction; owning engines manage prompt admission.
|
|
* - "preassembly_may_overflow": the precheck takes the maximum of the
|
|
* assembled estimate and the pre-assembly (unwindowed) session-history
|
|
* estimate. Engines opt into this when their assembled view can hide an
|
|
* overflow that would still affect the underlying transcript. This opt-in
|
|
* keeps the generic precheck active even for engines that own compaction.
|
|
*
|
|
* Defaults to "assembled".
|
|
*/
|
|
promptAuthority?: "assembled" | "preassembly_may_overflow";
|
|
/** Optional context-engine-provided instructions prepended to the runtime system prompt */
|
|
systemPromptAddition?: string;
|
|
/**
|
|
* Optional projection lifecycle for hosts with persistent backend threads.
|
|
*
|
|
* Context engines that return `thread_bootstrap` ask the host to inject the
|
|
* assembled context once for the supplied epoch, then reuse the backend
|
|
* thread until the epoch changes. Engines that omit this field retain the
|
|
* legacy per-turn projection behavior.
|
|
*/
|
|
contextProjection?: ContextEngineProjection;
|
|
};
|
|
|
|
export type ContextEngineProjection = {
|
|
/** How the assembled context should be projected into the backend runtime. */
|
|
mode: "per_turn" | "thread_bootstrap";
|
|
/** Stable context epoch. Changing this tells persistent backends to rotate. */
|
|
epoch?: string;
|
|
/** Optional diagnostic fingerprint for the projected context payload. */
|
|
fingerprint?: string;
|
|
};
|
|
|
|
export type ContextEngineOperation = "agent-run" | "manual-compact" | "subagent-spawn";
|
|
|
|
export type ContextEngineRuntimeMode = "normal" | "fallback" | "degraded";
|
|
|
|
export type ContextEngineSelectionSource = "configured" | "default" | "unknown";
|
|
|
|
export type ContextEngineRuntimeReasonCode =
|
|
| "provider_timeout"
|
|
| "provider_unavailable"
|
|
| "rate_limited"
|
|
| "context_overflow"
|
|
| "runtime_unavailable"
|
|
| "unknown";
|
|
|
|
export type ContextEngineHostCapability =
|
|
| "bootstrap"
|
|
| "assemble-before-prompt"
|
|
| "after-turn"
|
|
| "maintain"
|
|
| "compact"
|
|
| "runtime-llm-complete"
|
|
| "thread-bootstrap-projection";
|
|
|
|
export type ContextEngineHostRequirements = {
|
|
/** Host capabilities required before the engine can safely serve this operation. */
|
|
requiredCapabilities: ContextEngineHostCapability[];
|
|
/** Optional engine-authored guidance appended to the host compatibility error. */
|
|
unsupportedMessage?: string;
|
|
};
|
|
|
|
export type ContextEngineRuntimeSettings = {
|
|
schemaVersion: 1;
|
|
runtime: {
|
|
host: "openclaw";
|
|
mode: ContextEngineRuntimeMode;
|
|
harnessId: string | null;
|
|
runtimeId: string | null;
|
|
};
|
|
model: {
|
|
requested: string | null;
|
|
resolved: string | null;
|
|
provider: string | null;
|
|
family: string | null;
|
|
};
|
|
contextEngineSelection: {
|
|
selectedId: string | null;
|
|
source: ContextEngineSelectionSource;
|
|
};
|
|
executionHost: {
|
|
id: string | null;
|
|
label: string | null;
|
|
};
|
|
limits: {
|
|
promptTokenBudget: number | null;
|
|
maxOutputTokens: number | null;
|
|
};
|
|
diagnostics: {
|
|
fallbackReason: ContextEngineRuntimeReasonCode | null;
|
|
degradedReason: ContextEngineRuntimeReasonCode | null;
|
|
};
|
|
};
|
|
|
|
export class ContextEngineRuntimeSettingsUnavailableError extends Error {
|
|
readonly code = "context_engine_runtime_settings_unavailable";
|
|
constructor(message?: string) {
|
|
super(message);
|
|
this.name = "ContextEngineRuntimeSettingsUnavailableError";
|
|
}
|
|
}
|
|
|
|
export class ContextEngineRuntimeSettingsUnsupportedError extends Error {
|
|
readonly code = "context_engine_runtime_settings_unsupported";
|
|
constructor(message?: string) {
|
|
super(message);
|
|
this.name = "ContextEngineRuntimeSettingsUnsupportedError";
|
|
}
|
|
}
|
|
|
|
export type CompactResult = {
|
|
ok: boolean;
|
|
compacted: boolean;
|
|
reason?: string;
|
|
result?: {
|
|
summary?: string;
|
|
firstKeptEntryId?: string;
|
|
tokensBefore: number;
|
|
tokensAfter?: number;
|
|
details?: unknown;
|
|
/** Session id after compaction, when the runtime rotated transcripts. */
|
|
sessionId?: string;
|
|
/** Typed post-compaction live session target; successor when the runtime rotated transcripts. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
/**
|
|
* Raw session file path after compaction.
|
|
*
|
|
* @deprecated Use `sessionTarget`. Shipped plugin-sdk contract: released
|
|
* third-party context engines (v2026.6.x and earlier) report rotated
|
|
* transcripts through this field. Remove once typed session targets are
|
|
* the only successor contract.
|
|
*/
|
|
sessionFile?: string;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Resolve the post-compaction live transcript identity from a compact result.
|
|
*
|
|
* Prefers the typed `sessionTarget`. Reading the raw fields is the named
|
|
* compat path for shipped third-party engines that predate `sessionTarget`;
|
|
* it is removed together with the deprecated `sessionFile` result field.
|
|
*/
|
|
export function resolveCompactionSuccessorTranscript(result: CompactResult): {
|
|
sessionId?: string;
|
|
sessionFile?: string;
|
|
} {
|
|
const target = result.result?.sessionTarget;
|
|
return {
|
|
sessionId: target?.sessionId ?? result.result?.sessionId,
|
|
// Storage-neutral targets carry no raw locator; the deprecated raw field on
|
|
// the result remains the only file-era locator shipped engines report.
|
|
sessionFile: result.result?.sessionFile,
|
|
};
|
|
}
|
|
|
|
export type IngestResult = {
|
|
/** Whether the message was ingested (false if duplicate or no-op) */
|
|
ingested: boolean;
|
|
};
|
|
|
|
export type IngestBatchResult = {
|
|
/** Number of messages ingested from the supplied batch */
|
|
ingestedCount: number;
|
|
};
|
|
|
|
export type BootstrapResult = {
|
|
/** Whether bootstrap ran and initialized the engine's store */
|
|
bootstrapped: boolean;
|
|
/** Number of historical messages imported (if applicable) */
|
|
importedMessages?: number;
|
|
/** Optional reason when bootstrap was skipped */
|
|
reason?: string;
|
|
};
|
|
|
|
export type ContextEngineInfo = {
|
|
id: string;
|
|
name: string;
|
|
version?: string;
|
|
/** True when the engine manages its own compaction lifecycle. */
|
|
ownsCompaction?: boolean;
|
|
/**
|
|
* Controls how turn-triggered maintenance should be executed.
|
|
*
|
|
* Engines remain compatible by default unless the host explicitly opts into
|
|
* background turn maintenance.
|
|
*/
|
|
turnMaintenanceMode?: "foreground" | "background";
|
|
/**
|
|
* Host capability requirements for operations where using an unsupported
|
|
* runtime would silently degrade or corrupt the engine's behavior.
|
|
*/
|
|
hostRequirements?: Partial<Record<ContextEngineOperation, ContextEngineHostRequirements>>;
|
|
};
|
|
|
|
export type SubagentSpawnPreparation = {
|
|
/** Roll back pre-spawn setup when subagent launch fails. */
|
|
rollback: () => void | Promise<void>;
|
|
};
|
|
|
|
export type SubagentEndReason = "deleted" | "completed" | "swept" | "released";
|
|
|
|
export type TranscriptRewriteReplacement = {
|
|
/** Existing transcript entry id to replace on the active branch. */
|
|
entryId: string;
|
|
/** Replacement message content for that entry. */
|
|
message: AgentMessage;
|
|
};
|
|
|
|
export type TranscriptRewriteRequest = {
|
|
/** Message entry replacements to apply in one branch-and-reappend pass. */
|
|
replacements: TranscriptRewriteReplacement[];
|
|
/** Optional entry-id set that must cover every active-branch entry from the first replacement onward. */
|
|
allowedRewriteSuffixEntryIds?: string[];
|
|
};
|
|
|
|
export type TranscriptRewriteResult = {
|
|
/** Whether the active branch changed. */
|
|
changed: boolean;
|
|
/** Estimated bytes removed from the active branch message payloads. */
|
|
bytesFreed: number;
|
|
/** Number of transcript message entries rewritten. */
|
|
rewrittenEntries: number;
|
|
/** Optional reason when no rewrite occurred. */
|
|
reason?: string;
|
|
};
|
|
|
|
export type ContextEngineMaintenanceResult = TranscriptRewriteResult;
|
|
|
|
type ContextEnginePromptCacheRetention = "none" | "short" | "long" | "in_memory" | "24h";
|
|
|
|
type ContextEnginePromptCacheUsage = {
|
|
input?: number;
|
|
output?: number;
|
|
cacheRead?: number;
|
|
cacheWrite?: number;
|
|
contextUsage?:
|
|
| { state: "available"; promptTokens: number; totalTokens: number }
|
|
| { state: "unavailable" };
|
|
total?: number;
|
|
};
|
|
|
|
type ContextEnginePromptCacheObservationChangeCode =
|
|
| "cacheRetention"
|
|
| "model"
|
|
| "streamStrategy"
|
|
| "systemPrompt"
|
|
| "tools"
|
|
| "transport";
|
|
|
|
type ContextEnginePromptCacheObservationChange = {
|
|
code: ContextEnginePromptCacheObservationChangeCode;
|
|
detail: string;
|
|
};
|
|
|
|
type ContextEnginePromptCacheObservation = {
|
|
broke: boolean;
|
|
previousCacheRead?: number;
|
|
cacheRead?: number;
|
|
changes?: ContextEnginePromptCacheObservationChange[];
|
|
};
|
|
|
|
export type ContextEnginePromptCacheInfo = {
|
|
/** Runtime-resolved retention for the actual provider/model/request path. */
|
|
retention?: ContextEnginePromptCacheRetention;
|
|
/** Usage from the most recent API call, not accumulated retry/tool-loop totals. */
|
|
lastCallUsage?: ContextEnginePromptCacheUsage;
|
|
/** Result from the runtime's prompt-cache observability heuristic. */
|
|
observation?: ContextEnginePromptCacheObservation;
|
|
/** Last known cache-touch timestamp from runtime-managed cache-TTL bookkeeping. */
|
|
lastCacheTouchAt?: number;
|
|
/** Known cache expiry time when the runtime can source it confidently. */
|
|
expiresAt?: number;
|
|
};
|
|
|
|
type ContextEngineTranscriptStorageInfo = {
|
|
/**
|
|
* Authoritative transcript backend for this runtime turn.
|
|
*
|
|
* Hosts may still pass legacy locator fields such as `sessionFile` for older
|
|
* plugin contracts, but context engines should use this field to decide
|
|
* whether that locator is a live transcript source.
|
|
*/
|
|
kind: "sqlite";
|
|
};
|
|
|
|
export type ContextEngineSessionTarget = {
|
|
/** Agent that owns the session in the runtime store. */
|
|
agentId?: string;
|
|
/** Runtime session id to compact. */
|
|
sessionId?: string;
|
|
/** Stable session key used for aliases, policy, and store resolution. */
|
|
sessionKey?: string;
|
|
/** Session store path that scopes the SQLite-backed runtime session. */
|
|
storePath?: string;
|
|
/** Optional transport thread identity for session target resolution. */
|
|
threadId?: string | number;
|
|
};
|
|
|
|
export type ContextEngineRuntimeContext = Record<string, unknown> & {
|
|
/** Runtime task working directory; workspaceDir remains the agent bootstrap workspace. */
|
|
cwd?: string;
|
|
/**
|
|
* True when the host has explicitly opted this maintenance run into
|
|
* consuming deferred compaction debt.
|
|
*/
|
|
allowDeferredCompactionExecution?: boolean;
|
|
/** Runtime-resolved context window budget for the active model call. */
|
|
tokenBudget?: number;
|
|
/** Selected agent harness id when compaction delegates back to the runtime. */
|
|
agentHarnessId?: string;
|
|
/** Best-effort current prompt/context token estimate for this turn. */
|
|
currentTokenCount?: number;
|
|
/** Optional prompt-cache telemetry for cache-aware engines. */
|
|
promptCache?: ContextEnginePromptCacheInfo;
|
|
/** Authoritative transcript backend for this turn. */
|
|
transcriptStorage?: ContextEngineTranscriptStorageInfo;
|
|
/** Storage-neutral runtime session target for compaction delegation. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
/**
|
|
* Safe transcript rewrite helper implemented by the runtime.
|
|
*
|
|
* Engines decide what is safe to rewrite; the runtime owns how the session
|
|
* DAG is updated on disk.
|
|
*/
|
|
rewriteTranscriptEntries?: (
|
|
request: TranscriptRewriteRequest,
|
|
) => Promise<TranscriptRewriteResult>;
|
|
/** LLM completion capability for engines that need model inference. */
|
|
llm?: {
|
|
complete: (
|
|
params: import("../plugins/runtime/types-core.js").LlmCompleteParams,
|
|
) => Promise<import("../plugins/runtime/types-core.js").LlmCompleteResult>;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* ContextEngine defines the pluggable contract for context management.
|
|
*
|
|
* Required methods define a generic lifecycle; optional methods allow engines
|
|
* to provide additional capabilities (retrieval, lineage, etc.).
|
|
*/
|
|
export interface ContextEngine {
|
|
/** Engine identifier and metadata */
|
|
readonly info: ContextEngineInfo;
|
|
|
|
/**
|
|
* Initialize engine state for a session, optionally importing historical context.
|
|
*/
|
|
bootstrap?(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
sessionFile: string;
|
|
runtimeSettings?: ContextEngineRuntimeSettings;
|
|
runtimeContext?: ContextEngineRuntimeContext;
|
|
}): Promise<BootstrapResult>;
|
|
|
|
/**
|
|
* Run transcript maintenance after bootstrap, successful turns, or compaction.
|
|
*
|
|
* Engines can use runtimeContext.rewriteTranscriptEntries() to request safe
|
|
* branch-and-reappend transcript rewrites without depending on runner internals.
|
|
*/
|
|
maintain?(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
sessionFile: string;
|
|
runtimeSettings?: ContextEngineRuntimeSettings;
|
|
runtimeContext?: ContextEngineRuntimeContext;
|
|
}): Promise<ContextEngineMaintenanceResult>;
|
|
|
|
/**
|
|
* Ingest a single message into the engine's store.
|
|
*/
|
|
ingest(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
message: AgentMessage;
|
|
/** True when the message belongs to a heartbeat run. */
|
|
isHeartbeat?: boolean;
|
|
}): Promise<IngestResult>;
|
|
|
|
/**
|
|
* Ingest a completed turn batch as a single unit.
|
|
*/
|
|
ingestBatch?(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
messages: AgentMessage[];
|
|
/** True when the batch belongs to a heartbeat run. */
|
|
isHeartbeat?: boolean;
|
|
}): Promise<IngestBatchResult>;
|
|
|
|
/**
|
|
* Execute optional post-turn lifecycle work after a run attempt completes.
|
|
* Engines can use this to persist canonical context and trigger background
|
|
* compaction decisions.
|
|
*/
|
|
afterTurn?(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
/** Storage-neutral runtime session target for transcript/session SDK helpers. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
sessionFile: string;
|
|
messages: AgentMessage[];
|
|
/** Number of messages that existed before the prompt was sent. */
|
|
prePromptMessageCount: number;
|
|
/** Optional auto-compaction summary emitted by the runtime. */
|
|
autoCompactionSummary?: string;
|
|
/** True when this turn belongs to a heartbeat run. */
|
|
isHeartbeat?: boolean;
|
|
/** Optional model context token budget for proactive compaction. */
|
|
tokenBudget?: number;
|
|
/** Optional runtime-owned context for engines that need caller state. */
|
|
runtimeSettings?: ContextEngineRuntimeSettings;
|
|
runtimeContext?: ContextEngineRuntimeContext;
|
|
}): Promise<void>;
|
|
|
|
/**
|
|
* Assemble model context under a token budget.
|
|
* Returns an ordered set of messages ready for the model.
|
|
*/
|
|
assemble(params: {
|
|
sessionId: string;
|
|
sessionKey?: string;
|
|
messages: AgentMessage[];
|
|
tokenBudget?: number;
|
|
/** Tool names available for this run so engines can align prompt guidance with runtime tool access. */
|
|
availableTools?: Set<string>;
|
|
/** Active memory citation mode when engines want to mirror memory prompt guidance. */
|
|
citationsMode?: MemoryCitationsMode;
|
|
/** Current model identifier (e.g. "claude-opus-4", "gpt-4o", "qwen2.5-7b").
|
|
* Allows context engine plugins to adapt formatting per model. */
|
|
model?: string;
|
|
/** The incoming user prompt for this turn (useful for retrieval-oriented engines). */
|
|
prompt?: string;
|
|
runtimeSettings?: ContextEngineRuntimeSettings;
|
|
}): Promise<AssembleResult>;
|
|
|
|
/**
|
|
* Compact context to reduce token usage.
|
|
* May create summaries, prune old turns, etc.
|
|
*
|
|
* The host always bounds this call with a finite safety timeout (the same
|
|
* one that protects native runtime compaction). Engines that run long
|
|
* operations SHOULD additionally honor `abortSignal` so an in-flight
|
|
* compaction can be canceled promptly on run abort or host timeout instead
|
|
* of running to completion in the background.
|
|
*/
|
|
compact(params: {
|
|
sessionId: string;
|
|
sessionKey: string;
|
|
/** Caller-resolved owner agent for global session aliases. */
|
|
agentId?: string;
|
|
/** Storage-neutral runtime session target for delegated compaction. */
|
|
sessionTarget?: ContextEngineSessionTarget;
|
|
tokenBudget?: number;
|
|
/** Force compaction even below the default trigger threshold. */
|
|
force?: boolean;
|
|
/** Optional live token estimate from the caller's active context. */
|
|
currentTokenCount?: number;
|
|
/** Controls convergence target; defaults to budget. */
|
|
compactionTarget?: "budget" | "threshold";
|
|
customInstructions?: string;
|
|
/** Optional runtime-owned context for engines that need caller state. */
|
|
runtimeSettings?: ContextEngineRuntimeSettings;
|
|
runtimeContext?: ContextEngineRuntimeContext;
|
|
/**
|
|
* Optional abort signal honored before and during compaction. The host
|
|
* aborts it on run-level abort or when its compaction safety timeout
|
|
* fires; engines should stop work and reject promptly when it aborts.
|
|
*/
|
|
abortSignal?: AbortSignal;
|
|
}): Promise<CompactResult>;
|
|
|
|
/**
|
|
* Prepare context-engine-managed subagent state before the child run starts.
|
|
*
|
|
* Implementations can return a rollback handle that is invoked when spawn
|
|
* fails after preparation succeeds.
|
|
*/
|
|
prepareSubagentSpawn?(params: {
|
|
parentSessionKey: string;
|
|
childSessionKey: string;
|
|
contextMode?: "isolated" | "fork";
|
|
parentSessionId?: string;
|
|
parentSessionFile?: string;
|
|
childSessionId?: string;
|
|
childSessionFile?: string;
|
|
ttlMs?: number;
|
|
}): Promise<SubagentSpawnPreparation | undefined>;
|
|
|
|
/**
|
|
* Notify the context engine that a subagent lifecycle ended.
|
|
*/
|
|
onSubagentEnded?(params: { childSessionKey: string; reason: SubagentEndReason }): Promise<void>;
|
|
|
|
/**
|
|
* Dispose of any resources held by the engine.
|
|
*/
|
|
dispose?(): Promise<void>;
|
|
}
|