Skip to content
中文

ContextSelectionNodeDefinition ​

SUPPORT · type · Type contract

Definition of a selection node: like a processing node, but update receives chosen step IDs.

Import ​

ts
import type { ContextSelectionNodeDefinition } from '@jangts/agent-core/support';
js
/** @typedef {import('@jangts/agent-core/support').ContextSelectionNodeDefinition} ContextSelectionNodeDefinition */

Other public entry points:@jangts/agent-core/support, @jangts/agent-core/support/context.

Definition ​

Type: ContextSelectionNodeDefinition<State, Result, App>

Type expression
ts
type ContextSelectionNodeDefinition<State, Result, App> = Omit<
  ContextProcessingNodeDefinition<State, Result, App>,
  'update'
> & {
  /** Receives the chosen step IDs so the graph can route to reduction nodes. */
  readonly update: (result: ContextSelectionResult, state: Readonly<State>) => Partial<State>;
};

Type parameters ​

Type parameterConstraintDefault type
State——
Result——
App——

Field structure ​

FieldTypeRequiredDescription
idstringRequiredRead-only. Stable node id referenced by routes and error handling.
descriptionstringRequiredRead-only. Required explanation of what the node does; also used in diagnostics.
namestring | undefinedOptionalRead-only. Display name; defaults to id when omitted.
requiresreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys that must be present before this node runs; enforced by the engine.
providesreadonly (keyof State & string)[] | undefinedOptionalRead-only. State keys this node is expected to produce; validated after run.
routesreadonly WorkflowRoute<State, Result, App>[]RequiredRead-only. Candidate successors, evaluated in order. A getter must be pure; registration reads it once.
startsRoundboolean | undefinedOptionalRead-only. 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.
onErrorNodeIdstring | undefinedOptionalRead-only. Node entered when run/provides/route fails; contract errors always propagate instead.
onErrorRouteIdstring | undefinedOptionalRead-only. Route id reported with the recovery transition.
prepared((state: Readonly<State>, context: WorkflowContext<App>) => PreparedModelCall) | undefinedOptionalRead-only. Optional prebuilt model call, used instead of preparing request.
plan(state: Readonly<State>, context: WorkflowContext<App>) => ContextPlanRequiredRead-only. 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; }) | undefinedOptionalRead-only. Model preparation request, either static or derived from the current node state.
policyContextPolicy | undefinedOptionalRead-only. Processing policy; omitted means validate (no reduction, audit checks only).
timeoutMsnumber | undefinedOptionalRead-only. Per-node timeout in milliseconds; defaults to the Core call timeout.
compressorsreadonly ContextCompressor[] | undefinedOptionalRead-only. Compressors referenced by compression steps; validated against the policy at creation.
selectorsreadonly ContextSelector[] | undefinedOptionalRead-only. Selectors referenced by model-driven selection; validated against the policy at creation.
update(result: ContextSelectionResult, state: Readonly<State>) => Partial<State>RequiredRead-only. Receives the chosen step IDs so the graph can route to reduction nodes.

Member index ​

MemberPurpose
planBuilds the context plan; must be synchronous so budget failures surface before any I/O.
updateReceives the chosen step IDs so the graph can route to reduction nodes.

Member details ​

plan ​

Builds the context plan; must be synchronous so budget failures surface before any I/O.

ts
ContextSelectionNodeDefinition.plan(state: Readonly<State>, context: WorkflowContext<App>): ContextPlan
ParameterTypePassingDescription
stateReadonly<State>Required—
contextWorkflowContext<App>Required—
Fields of context
FieldTypeRequiredDescription
roundIndexnumberRequiredRead-only. Zero-based bounded round; phases within a round do not consume another round.
report(update: WorkflowNodeReport) => voidRequiredReport progress while this node is active; Core supplies its execution identity.
diagnosticsDiagnosticContext | undefinedOptionalRead-only. Diagnostic scope of this node visit, when recording is enabled.
modelWorkflowModelRequiredRead-only. 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>>; }RequiredRead-only. See the type definition and usage context.
errorunknownOptionalRead-only. Failure that led into this node, present only while entering an onErrorNodeId target.
errorEventIdstring | undefinedOptionalRead-only. Event id of that failure, for correlation in host logs.
appunknown extends App ? App : Readonly<App>RequiredRead-only. See the type definition and usage context.
loggerSubFlowLog | undefinedOptionalRead-only. Explicit optional recorder for this operation; never inferred from diagnostics.
signalAbortSignalRequiredRead-only. Non-optional cancellation signal; never undefined once execution has started.
createSubFlowLogger() => SubFlowLoggerRequiredBound to this context and owned by runtime; repeated calls in one visit return the same instance.
cacheNodeCacheRequiredRead-only. See the type definition and usage context.
agentCacheNodeAgentCache | undefinedOptionalRead-only. See the type definition and usage context.

Returns: ContextPlan.

Return value structure
FieldTypeRequiredDescription
fragmentsreadonly ContextFragment[]RequiredRead-only. Fragments in the order supplied by the App; assembly preserves it.
maxInputCharsnumberRequiredCharacter budget Core validates after assembly.
additionalMessagesreadonly (ModelMessage & { role: "user"; })[] | undefinedOptionalProtected user messages (for example image inputs); text counts toward the same budget.
originalFragmentsreadonly ContextFragment[] | undefinedOptionalTrusted originals for structural mutation auditing; never sent to the model.
mutableFragmentIdsreadonly string[] | undefinedOptionalExplicit value-mutation allowance when originals are supplied.

update ​

Receives the chosen step IDs so the graph can route to reduction nodes.

ts
ContextSelectionNodeDefinition.update(result: ContextSelectionResult, state: Readonly<State>): Partial<State>
ParameterTypePassingDescription
resultContextSelectionResultRequired—
stateReadonly<State>Required—
Fields of result
FieldTypeRequiredDescription
stepIdsreadonly string[]RequiredRead-only. Registered reduction step IDs chosen for execution; selection itself executes nothing.
planContextPlanRequiredRead-only. Plan describing current fragments at the full (unreduced) input limit.
preparedPreparedModelCall<unknown>RequiredRead-only. Model call prepared for this stage.
reportContextProcessingReportRequiredRead-only. Processing report accumulated by this and preceding steps.

Returns: Partial<State>.

Examples ​

Validate and assemble only, without compression yet ​

Beginner · 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: '状态?' }));

Add a history trimming policy to the same node contract ​

Configuration · Node.js

Put this node back into the same Workflow as the previous example; each run just adds history to State, and the model reply node does not change its interface. In a complete flow the reply target must exist.

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);

API reference, usage examples and developer guides.