实际请求测量与同次准备快照
需要提前处理上下文时才 prepare;多次测量与最终发送复用同一次传输准备。
普通 invoke 无需强制增加 prepare 步骤。prepare 固定当次动态传输指令、Schema、选项及 collector 工厂;measure 允许多次检查候选,不花模型调用次数。
measure 包含实际正文、传输指令和声明的计量,并分别展示 messageChars、instructionChars、schemaChars、transportChars、inputChars。输入 token 限额只有注入明确计数器后才存在;它已扣除本次输出预留和安全余量。
准备句柄属于创建它的本次 Runner/Workflow 请求,只能最终消费一次,不能更换 transport、stageId 或输出预留。测量不是预算预订或放行凭证:最终 Provider 前仍会重新检查。取消、过期、外部句柄及重复消费均会拒绝。
由简到繁的同业务示例
普通调用仍然只有 invoke
入门 · Node.js
ts
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages: readonly { content: string }[]) {
yield '收到:' + messages.at(-1)!.content;
},
};
const runner = new ModelRunner({ provider });
console.log((await runner.invoke('你好')).value);js
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages) {
yield '收到:' + messages.at(-1).content;
},
};
const runner = new ModelRunner({ provider });
console.log((await runner.invoke('你好')).value);只在需要测量时准备一次
配置 · Node.js
ts
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages: readonly { content: string }[]) {
yield '收到:' + messages.at(-1)!.content;
},
};
const runner = new ModelRunner({ provider, maxInputChars: 1000 });
const prepared = runner.prepare({ stageId: 'reply', maxOutputTokens: 400 });
const input = '你好,解释这次服务状态';
console.log(prepared.measure(input));
const result = await runner.invoke({ input, prepared });
console.log(result.value);js
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages) {
yield '收到:' + messages.at(-1).content;
},
};
const runner = new ModelRunner({ provider, maxInputChars: 1000 });
const prepared = runner.prepare({ stageId: 'reply', maxOutputTokens: 400 });
const input = '你好,解释这次服务状态';
console.log(prepared.measure(input));
const result = await runner.invoke({ input, prepared });
console.log(result.value);对同一准备句柄检查多份候选
扩展 · Node.js
仅演示 App 自己决定候选;删减真实上下文时仍要保持原问题、授权与证据完整。
ts
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages: readonly { content: string }[]) {
yield '收到:' + messages.at(-1)!.content;
},
};
const runner = new ModelRunner({ provider, maxInputChars: 1000 });
const prepared = runner.prepare({ stageId: 'reply' });
const withHistory = [{ role: 'user' as const, content: '历史:上次正常。\n本轮:现在呢?' }];
const currentOnly = [{ role: 'user' as const, content: '现在的服务状态?' }];
const selected = prepared.measure(withHistory).withinBudget ? withHistory : currentOnly;
if (!prepared.measure(selected).withinBudget) throw new Error('输入仍超限');
console.log((await runner.invoke({ input: selected, prepared })).value);js
import { ModelRunner } from '@jangts/agent-core/model';
const provider = {
async *stream(messages) {
yield '收到:' + messages.at(-1).content;
},
};
const runner = new ModelRunner({ provider, maxInputChars: 1000 });
const prepared = runner.prepare({ stageId: 'reply' });
const withHistory = [{ role: 'user', content: '历史:上次正常。\n本轮:现在呢?' }];
const currentOnly = [{ role: 'user', content: '现在的服务状态?' }];
const selected = prepared.measure(withHistory).withinBudget ? withHistory : currentOnly;
if (!prepared.measure(selected).withinBudget)
throw new Error('输入仍超限');
console.log((await runner.invoke({ input: selected, prepared })).value);