ContextProcessingNodeDefinition
SUPPORT · type · 类型合同
Definition accepted by createContextProcessingNode.
It is a normal Core WorkflowNode except that the node body is declared here: plan builds the context, update decides the committed state, and policy/handlers/timeout are validated when the node is created.
导入
ts
import type { ContextProcessingNodeDefinition } from '@jangts/agent-core/support';js
/** @typedef {import('@jangts/agent-core/support').ContextProcessingNodeDefinition} ContextProcessingNodeDefinition */其他公开入口:@jangts/agent-core/support、@jangts/agent-core/support/context。
定义
类型: ContextProcessingNodeDefinition<State, Result, App>
类型表达式
ts
type ContextProcessingNodeDefinition<State, Result, App> = Omit<
WorkflowNode<State, Result, App>,
'run' | 'report'
> & {
/** Builds the context plan; must be synchronous so budget failures surface before any I/O. */
readonly plan: (state: Readonly<State>, context: WorkflowContext<App>) => ContextPlan;
/** Model preparation request, either static or derived from the current node state. */
readonly request?:
| (ModelPrepareRequest<string | ModelTransportDefinition> & { modelId?: string })
| ((
state: Readonly<State>,
context: WorkflowContext<App>,
) => ModelPrepareRequest<string | ModelTransportDefinition> & { modelId?: string });
/** Maps the node result to the state fields to commit; return only changed fields. */
readonly update: (result: ContextNodeResult, state: Readonly<State>) => Partial<State>;
/** Optional prebuilt model call, used instead of preparing `request`. */
readonly prepared?: (state: Readonly<State>, context: WorkflowContext<App>) => PreparedModelCall;
/** Processing policy; omitted means `validate` (no reduction, audit checks only). */
readonly policy?: ContextPolicy;
/** Compressors referenced by compression steps; validated against the policy at creation. */
readonly compressors?: readonly ContextCompressor[];
/** Selectors referenced by model-driven selection; validated against the policy at creation. */
readonly selectors?: readonly ContextSelector[];
/** Per-node timeout in milliseconds; defaults to the Core call timeout. */
readonly timeoutMs?: number;
};泛型参数
| 类型参数 | 约束 | 默认类型 |
|---|---|---|
State | — | — |
Result | — | — |
App | — | — |
字段结构
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
id | string | 必需 | 只读。Stable node id referenced by routes and error handling. |
description | string | 必需 | 只读。Required explanation of what the node does; also used in diagnostics. |
name | string | undefined | 可省略 | 只读。Display name; defaults to id when omitted. |
requires | readonly (keyof State & string)[] | undefined | 可省略 | 只读。State keys that must be present before this node runs; enforced by the engine. |
provides | readonly (keyof State & string)[] | undefined | 可省略 | 只读。State keys this node is expected to produce; validated after run. |
routes | readonly WorkflowRoute<State, Result, App>[] | 必需 | 只读。Candidate successors, evaluated in order. A getter must be pure; registration reads it once. |
startsRound | boolean | undefined | 可省略 | 只读。Reserves a fresh round on entry. Use it for steps that may legitimately repeat; entering such a node when the round budget is exhausted fails with the configured exhausted error. |
onErrorNodeId | string | undefined | 可省略 | 只读。Node entered when run/provides/route fails; contract errors always propagate instead. |
onErrorRouteId | string | undefined | 可省略 | 只读。Route id reported with the recovery transition. |
plan | (state: Readonly<State>, context: WorkflowContext<App>) => ContextPlan | 必需 | 只读。Builds the context plan; must be synchronous so budget failures surface before any I/O. |
request | (ModelPrepareRequest<string | ModelTransportDefinition<unknown>> & { modelId?: string; }) | ((state: Readonly<State>, context: WorkflowContext<App>) => ModelPrepareRequest<string | ModelTransportDefinition> & { modelId?: string; }) | undefined | 可省略 | 只读。Model preparation request, either static or derived from the current node state. |
update | (result: ContextNodeResult, state: Readonly<State>) => Partial<State> | 必需 | 只读。Maps the node result to the state fields to commit; return only changed fields. |
prepared | ((state: Readonly<State>, context: WorkflowContext<App>) => PreparedModelCall) | undefined | 可省略 | 只读。Optional prebuilt model call, used instead of preparing request. |
policy | ContextPolicy | undefined | 可省略 | 只读。Processing policy; omitted means validate (no reduction, audit checks only). |
compressors | readonly ContextCompressor[] | undefined | 可省略 | 只读。Compressors referenced by compression steps; validated against the policy at creation. |
selectors | readonly ContextSelector[] | undefined | 可省略 | 只读。Selectors referenced by model-driven selection; validated against the policy at creation. |
timeoutMs | number | undefined | 可省略 | 只读。Per-node timeout in milliseconds; defaults to the Core call timeout. |
成员目录
| 成员 | 用途 |
|---|---|
plan | Builds the context plan; must be synchronous so budget failures surface before any I/O. |
update | Maps the node result to the state fields to commit; return only changed fields. |
成员详情
plan
Builds the context plan; must be synchronous so budget failures surface before any I/O.
ts
ContextProcessingNodeDefinition.plan(state: Readonly<State>, context: WorkflowContext<App>): ContextPlan| 参数 | 类型 | 传递 | 说明 |
|---|---|---|---|
state | Readonly<State> | 必需 | — |
context | WorkflowContext<App> | 必需 | — |
context 的字段
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
roundIndex | number | 必需 | 只读。Zero-based bounded round; phases within a round do not consume another round. |
report | (update: WorkflowNodeReport) => void | 必需 | Report progress while this node is active; Core supplies its execution identity. |
diagnostics | DiagnosticContext | undefined | 可省略 | 只读。Diagnostic scope of this node visit, when recording is enabled. |
model | WorkflowModel | 必需 | 只读。Model access limited by the workflow's configured calls and budget. |
tools | { invoke(request: Omit<import("../capabilities/tools.js").ToolInvocationRequest, "diagnostics">): Promise<import("../invocation.js").ToolResult<unknown>>; } | 必需 | 只读。见类型定义及调用场景。 |
error | unknown | 可省略 | 只读。Failure that led into this node, present only while entering an onErrorNodeId target. |
errorEventId | string | undefined | 可省略 | 只读。Event id of that failure, for correlation in host logs. |
app | unknown extends App ? App : Readonly<App> | 必需 | 只读。见类型定义及调用场景。 |
logger | SubFlowLog | undefined | 可省略 | 只读。Explicit optional recorder for this operation; never inferred from diagnostics. |
signal | AbortSignal | 必需 | 只读。Non-optional cancellation signal; never undefined once execution has started. |
createSubFlowLogger | () => SubFlowLogger | 必需 | Bound to this context and owned by runtime; repeated calls in one visit return the same instance. |
cache | NodeCache | 必需 | 只读。见类型定义及调用场景。 |
agentCache | NodeAgentCache | undefined | 可省略 | 只读。见类型定义及调用场景。 |
返回: ContextPlan。
返回值结构
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
fragments | readonly ContextFragment[] | 必需 | 只读。Fragments in the order supplied by the App; assembly preserves it. |
maxInputChars | number | 必需 | Character budget Core validates after assembly. |
additionalMessages | readonly (ModelMessage & { role: "user"; })[] | undefined | 可省略 | Protected user messages (for example image inputs); text counts toward the same budget. |
originalFragments | readonly ContextFragment[] | undefined | 可省略 | Trusted originals for structural mutation auditing; never sent to the model. |
mutableFragmentIds | readonly string[] | undefined | 可省略 | Explicit value-mutation allowance when originals are supplied. |
update
Maps the node result to the state fields to commit; return only changed fields.
ts
ContextProcessingNodeDefinition.update(result: ContextNodeResult, state: Readonly<State>): Partial<State>| 参数 | 类型 | 传递 | 说明 |
|---|---|---|---|
result | ContextNodeResult | 必需 | — |
state | Readonly<State> | 必需 | — |
result 的字段
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
input | BuiltContext | 必需 | 只读。Context built from the processed fragments, sized against the full input limit. |
prepared | PreparedModelCall<unknown> | 必需 | 只读。Model call prepared for this stage; carries measurement and remaining call budget. |
report | ContextProcessingReport | 必需 | 只读。What processing changed: characters, token usage, selection decisions and reductions. |
返回: Partial<State>。
使用示例
- 上下文处理是普通 Workflow 节点:通过正常节点与路由接入选择、裁切、压缩,Core 统一记录并调度它们。
只验证与装配,先不增加压缩
入门 · Node.js
ts
import { AgentCoreEngine, defineWorkflow, route } from '@jangts/agent-core/engine';
import { Support } from '@jangts/agent-core';
import type { BuiltContext, PreparedModelCall } from '@jangts/agent-core/types';
type State = { question: string; input?: BuiltContext; prepared?: PreparedModelCall; answer?: string };
const builder = Support.defineContextFragments<State>([
{ id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
], { maxInputChars: 2000 });
const prepare = Support.createContextProcessingNode<State, string>({
id: 'prepare', description: '装配并校验输入', startsRound: true,
plan: state => builder.plan({ input: state }),
update: result => ({ input: result.input, prepared: result.prepared }),
routes: [route.to('reply')],
});
const workflow = defineWorkflow<State, string>({ id: 'chat', nodes: [prepare, {
id: 'reply', description: '使用同次准备回答', requires: ['input', 'prepared'],
async run(state, { model }) { const { value } = await model.invoke({ input: state.input!, prepared: state.prepared! }); return { answer: String(value) }; },
routes: [route.deliver('answer')],
}] });
const agent = new AgentCoreEngine({ workflow, model: { provider: { async *stream() { yield '服务正常'; } } } });
console.log(await agent.run({ question: '状态?' }));js
import { AgentCoreEngine, defineWorkflow, route } from '@jangts/agent-core/engine';
import { Support } from '@jangts/agent-core';
const builder = Support.defineContextFragments([
{ id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
], { maxInputChars: 2000 });
const prepare = Support.createContextProcessingNode({
id: 'prepare', description: '装配并校验输入', startsRound: true,
plan: state => builder.plan({ input: state }),
update: result => ({ input: result.input, prepared: result.prepared }),
routes: [route.to('reply')],
});
const workflow = defineWorkflow({ id: 'chat', nodes: [prepare, {
id: 'reply', description: '使用同次准备回答', requires: ['input', 'prepared'],
async run(state, { model }) { const { value } = await model.invoke({ input: state.input, prepared: state.prepared }); return { answer: String(value) }; },
routes: [route.deliver('answer')],
}] });
const agent = new AgentCoreEngine({ workflow, model: { provider: { async *stream() { yield '服务正常'; } } } });
console.log(await agent.run({ question: '状态?' }));同一节点合同增加历史裁切策略
配置 · Node.js
将该节点放回前例相同 Workflow;每次 run 的 State 增加 history 即可,模型 reply 节点不换接口。完整流程里的 reply 目标必须存在。
ts
import { Support } from '@jangts/agent-core';
import { route } from '@jangts/agent-core/engine';
import type { BuiltContext, PreparedModelCall } from '@jangts/agent-core/types';
type State = { question: string; history: { role: string; content: string }[]; input?: BuiltContext; prepared?: PreparedModelCall };
const builder = Support.defineContextFragments<State>([
{ id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
{ id: 'history', sourceId: 'conversation', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 10000, format: state => ({ messages: state.history }) },
], { maxInputChars: 1200 });
const prepare = Support.createContextProcessingNode<State, string>({
id: 'prepare', description: '按需要裁切旧历史', startsRound: true,
plan: state => builder.plan({ input: state }),
policy: { mode: 'reduce', steps: [{ id: 'recent', kind: 'trim', fragmentId: 'history', field: 'messages',
targetChars: 700, grouping: { kind: 'user-turn' }, keepGroups: 1 }] },
update: result => ({ input: result.input, prepared: result.prepared }),
routes: [route.to('reply')],
});
console.log(prepare.id);js
import { Support } from '@jangts/agent-core';
import { route } from '@jangts/agent-core/engine';
const builder = Support.defineContextFragments([
{ id: 'question', sourceId: 'request', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 1000, format: state => state.question },
{ id: 'history', sourceId: 'conversation', trust: 'user', lifetime: 'turn', role: 'user', maxChars: 10000, format: state => ({ messages: state.history }) },
], { maxInputChars: 1200 });
const prepare = Support.createContextProcessingNode({
id: 'prepare', description: '按需要裁切旧历史', startsRound: true,
plan: state => builder.plan({ input: state }),
policy: { mode: 'reduce', steps: [{ id: 'recent', kind: 'trim', fragmentId: 'history', field: 'messages',
targetChars: 700, grouping: { kind: 'user-turn' }, keepGroups: 1 }] },
update: result => ({ input: result.input, prepared: result.prepared }),
routes: [route.to('reply')],
});
console.log(prepare.id);