fix(ai): persist context requests and enforce agent execution order
This commit is contained in:
@@ -218,4 +218,30 @@ describe('AgentService', () => {
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('persists a response requesting source or logs even without commands or changes', () => {
|
||||
const service = Object.create(AgentService.prototype) as unknown as {
|
||||
parseSyncedMessage: (value: Record<string, unknown>, index: number) => {
|
||||
plan: { requestedModules: string[]; requestedLogs: string[] };
|
||||
};
|
||||
};
|
||||
const message = service.parseSyncedMessage({
|
||||
id: 'agent-plan-context',
|
||||
role: 'assistant',
|
||||
content: '차량 설정 파일을 확인하겠습니다.',
|
||||
plan: {
|
||||
summary: '차량 설정 파일을 확인하겠습니다.',
|
||||
explanation: '조향 방식 설정을 확인하려면 차량 소스가 필요합니다.',
|
||||
requestedModules: ['NAV2-MKMini'],
|
||||
requestedLogs: ['NAV2-Control'],
|
||||
actionPlan: ['차량 설정 확인'],
|
||||
commands: [],
|
||||
changes: [],
|
||||
createModule: null,
|
||||
},
|
||||
}, 0);
|
||||
|
||||
expect(message.plan.requestedModules).toEqual(['NAV2-MKMini']);
|
||||
expect(message.plan.requestedLogs).toEqual(['NAV2-Control']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -311,6 +311,11 @@ export class AgentService {
|
||||
let plan: AgentPlan | null = null;
|
||||
if (rawPlan) {
|
||||
const moduleNames = new Set<string>();
|
||||
for (const field of ['requestedModules', 'requestedLogs']) {
|
||||
for (const name of Array.isArray(rawPlan[field]) ? rawPlan[field] : []) {
|
||||
if (typeof name === 'string') moduleNames.add(name.trim());
|
||||
}
|
||||
}
|
||||
for (const command of Array.isArray(rawPlan.commands)
|
||||
? rawPlan.commands
|
||||
: []) {
|
||||
@@ -744,7 +749,12 @@ export class AgentService {
|
||||
'학생이 정보 확인이나 설명만 요청하면 제공된 입력만 근거로 답하고 changes는 빈 배열, createModule은 null로 반환한다.',
|
||||
'작업이 여러 단계라면 actionPlan에 학생이 이해할 수 있는 짧은 단계 목록을 순서대로 작성한다.',
|
||||
'빌드, 테스트, 진단 명령 실행이 필요하면 commands에 현재 단계에서 실행할 다음 승인 명령만 넣는다. 명령은 해당 모듈 루트에서 실행된다.',
|
||||
'파일 변경과 commands를 함께 반환하면 모든 명령은 파일 변경 적용 후 실행할 검증 명령이어야 하며, actionPlan에도 파일 변경을 명령보다 먼저 적는다.',
|
||||
'파일 변경 전에 실행해야 하는 사전 진단 명령이라면 changes를 비우고 명령만 먼저 반환한다. 실행 결과가 다음 요청에 제공되면 그때 변경안을 제안한다.',
|
||||
'commands는 읽기, 빌드, 테스트, 실행 진단에 필요한 최소 명령만 제안하고 sudo, 시스템 설정 변경, 삭제, 재부팅, 자격증명 접근 명령은 절대 제안하지 않는다.',
|
||||
'ros2 run 또는 ros2 launch는 대상 모듈의 state가 running일 때만 제안한다. 이 명령은 해당 모듈 컨테이너 안에서 최대 20초간 관찰 실행된다.',
|
||||
'ros2 실행이 필요한 대상 모듈의 state가 stopped이면 commands에 command가 정확히 "lms module start"인 모듈 시작 승인 액션 하나만 반환한다. 학생이 승인하면 LMS가 모듈을 시작하고 결과를 다음 요청에 제공한다.',
|
||||
'모듈 시작 액션이 승인되기 전에는 ros2 run 또는 ros2 launch를 함께 제안하지 않는다. ros2 topic pub, service call, action send_goal 같은 ROS2 제어 명령은 제안하지 않는다.',
|
||||
'명령에는 cd를 포함하지 말고 source 연결은 &&만 사용한다. 한 명령은 한 줄로 작성한다.',
|
||||
'기존 모듈 변경은 전달받은 moduleName만 사용한다. 새 모듈 요청일 때만 createModule을 채운다.',
|
||||
'launchFile은 모듈 루트 기준 상대 경로다. 파일 path도 각 모듈 루트 기준 상대 경로다.',
|
||||
|
||||
Reference in New Issue
Block a user