createContextReductionNode
SUPPORT · function · 运行时值
Create a node that applies exactly one registered reduction step.
Partial plans keep the full budget until final assembly, so intermediate nodes do not shrink the allowance reserved for the reply.
导入
ts
import { createContextReductionNode } from '@jangts/agent-core/support';js
import { createContextReductionNode } from '@jangts/agent-core/support';其他公开入口:@jangts/agent-core/support、@jangts/agent-core/support/context。
定义
泛型参数
| 类型参数 | 约束 | 默认类型 |
|---|---|---|
State | — | — |
Result | — | — |
App | — | undefined |
调用
ts
createContextReductionNode<State, Result, App = undefined>(definition: ContextReductionNodeDefinition<State, Result, App>): WorkflowNode<State, Result, App>Create a node that applies exactly one registered reduction step.
Partial plans keep the full budget until final assembly, so intermediate nodes do not shrink the allowance reserved for the reply.
| 类型参数 | 约束 | 默认类型 |
|---|---|---|
State | — | — |
Result | — | — |
App | — | undefined |
| 参数 | 类型 | 传递 | 说明 |
|---|---|---|---|
definition | ContextReductionNodeDefinition<State, Result, App> | 必需 | — |
definition 的字段
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
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. |
prepared | ((state: Readonly<State>, context: WorkflowContext<App>) => PreparedModelCall) | undefined | 可省略 | 只读。Optional prebuilt model call, used instead of preparing request. |
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. |
policy | ContextPolicy | undefined | 可省略 | 只读。Processing policy; omitted means validate (no reduction, audit checks only). |
timeoutMs | number | undefined | 可省略 | 只读。Per-node timeout in milliseconds; defaults to the Core call timeout. |
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. |
stepId | string | ((state: Readonly<State>) => string) | 必需 | 只读。ID of the reduction step to run, fixed or derived from state. |
update | (result: ContextStageResult, state: Readonly<State>) => Partial<State> | 必需 | 只读。Receives the stage result after one reduction has been applied. |
返回: WorkflowNode<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. |
report | ((update: void | Readonly<Partial<State>>, context: NodeReportingContext) => WorkflowNodeReport) | undefined | 可省略 | 只读。Optional application-reported detail, collected only when content logging is enabled. |
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. |
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. |
run | ((state: Readonly<State>, context: WorkflowContext<App>) => void | Partial<State> | Promise<void | Partial<State>>) | undefined | 可省略 | 只读。Return only changed fields. Core commits them after cancellation and output checks. |
使用示例
- 上下文处理是普通 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);