fix(teacher): 区分词元预算与传输字节避免短问题被拦截
This commit is contained in:
@@ -61,7 +61,7 @@ afterEach(async () => {
|
||||
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
||||
vi.useRealTimers();
|
||||
});
|
||||
async function fixture({ durableSource = false, sourceContext = context, liveModel = false, cloudTeacher = false, mockCloud = false, modelInputLimit = definition.limits.max_input_tokens } = {}) {
|
||||
async function fixture({ durableSource = false, sourceContext = context, liveModel = false, cloudTeacher = false, mockCloud = false, modelInputLimit = definition.limits.max_input_tokens, modelSystemPrompt = definition.system_prompt } = {}) {
|
||||
const root = await mkdtemp(path.join(tmpdir(), 'coding-teacher-'));
|
||||
roots.push(root);
|
||||
const projects = new CodingProjectService(
|
||||
@@ -114,7 +114,7 @@ async function fixture({ durableSource = false, sourceContext = context, liveMod
|
||||
yuxi: { agent_slug: 'teacher', agent_version: 2 } } }] }) : undefined,
|
||||
version: async (_account, v) => ({
|
||||
version: v,
|
||||
payload: { ...definition, name: '老师 v' + v, limits: { ...definition.limits, max_input_tokens: modelInputLimit } },
|
||||
payload: { ...definition, name: '老师 v' + v, system_prompt: modelSystemPrompt, limits: { ...definition.limits, max_input_tokens: modelInputLimit } },
|
||||
}),
|
||||
preview: async (_account, revision) => {
|
||||
if (revision !== 2) throw new TeacherError(409, 'teacher_draft_changed', '草稿变化');
|
||||
@@ -170,7 +170,9 @@ describe('cloud coding teacher', () => {
|
||||
expect((await f.service.list(f.scope)).lastSelectedTopicId).toBe(selected.id);
|
||||
});
|
||||
it('wires the Yuxi topic through scoped credentials and local tools without a local prompt or model loop', async () => {
|
||||
const f = await fixture({ cloudTeacher: true });
|
||||
const f = await fixture({ cloudTeacher: true, sourceContext: {
|
||||
...context, messages: [{ id: 'long-code', role: 'assistant', text: 'const title = "game";\n'.repeat(500) }],
|
||||
} });
|
||||
await writeFile(path.join(f.created.project.path, 'counter.ts'), 'let count = 42;');
|
||||
vi.spyOn(teacherCloud, 'assertTeacherAccount').mockReturnValue(undefined);
|
||||
vi.spyOn(teacherCloud, 'teacherCloudRequest').mockResolvedValue({
|
||||
@@ -198,7 +200,9 @@ describe('cloud coding teacher', () => {
|
||||
const saved = (await f.service.read(f.scope, topic.id)).requests[0];
|
||||
expect(saved.response).toBe('计数器从 42 开始。');
|
||||
expect(saved.cloudRequestId).toBe('cloud-question');
|
||||
expect(JSON.stringify(requests[0].body)).toContain('创建计数器');
|
||||
expect(JSON.stringify(requests[0].body)).toContain('const title');
|
||||
expect(saved.truncatedMessages).toBeGreaterThan(0);
|
||||
expect(Buffer.byteLength((requests[0].body as { query: string }).query)).toBeLessThanOrEqual(8000);
|
||||
expect(requests.find(item => item.path.endsWith('/tool-results'))?.body).toMatchObject({
|
||||
context_id: id, results: [{ tool_call_id: 'read-counter', status: 'success', content: expect.stringContaining('let count = 42;') }],
|
||||
});
|
||||
@@ -1102,7 +1106,7 @@ describe('teacher context and wire contract', () => {
|
||||
expect(compiled.messages[0].content).toContain(TEACHER_BEHAVIOR_PROMPT);
|
||||
expect(compiled.includedSourceMessageIds).toEqual(['source-user']);
|
||||
expect(compiled.omittedMessages).toBe(1);
|
||||
expect(() => compileTeacherContext(definition, context, [], 'x'.repeat(9000), [])).toThrow(
|
||||
expect(() => compileTeacherContext(definition, context, [], 'x'.repeat(18000), [])).toThrow(
|
||||
'超过上下文预算'
|
||||
);
|
||||
});
|
||||
@@ -1297,7 +1301,14 @@ it.each(['teacher', 'friend'] as const)('routes project-level %s config and topi
|
||||
|
||||
describe('structured teacher service integration', () => {
|
||||
it.each(['suggestions', 'discussion'] as const)('parses only final %s JSON after the real local runner reads a project file', async (format) => {
|
||||
const f = await fixture({ liveModel: true, modelInputLimit: 24000 });
|
||||
const f = await fixture({
|
||||
liveModel: true, modelInputLimit: 8000,
|
||||
modelSystemPrompt: '帮助学生理解设计,结合实际进展给出建议。'.repeat(45),
|
||||
sourceContext: { ...context, messages: [
|
||||
{ id: 'current-question', role: 'user', text: '创建计数器' },
|
||||
{ id: 'long-code', role: 'assistant', text: 'const title = "game";\n'.repeat(500) },
|
||||
] },
|
||||
});
|
||||
const scope = { ...f.scope, sourceId: 'project', role: 'teacher' as const };
|
||||
await writeFile(path.join(f.created.project.path, 'counter.ts'), 'let count = 42;');
|
||||
vi.spyOn(teacherCloud, 'assertTeacherAccount').mockReturnValue(undefined);
|
||||
|
||||
Reference in New Issue
Block a user