wip: next round of implementation, this time tests
This commit is contained in:
@@ -36,4 +36,42 @@ describe('WorkflowCheckpointStore', () => {
|
||||
expect(loaded?.pendingFields).toEqual(['date']);
|
||||
expect(loaded?.lastTraceId).toBe('trace-1');
|
||||
});
|
||||
|
||||
it('returns null when no checkpoint exists', async () => {
|
||||
const adapter = new InMemorySettingsAdapter();
|
||||
const store = new WorkflowCheckpointStore(adapter);
|
||||
|
||||
const loaded = await store.load('missing-conversation');
|
||||
|
||||
expect(loaded).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for malformed checkpoint JSON', async () => {
|
||||
const adapter = new InMemorySettingsAdapter();
|
||||
await adapter.setSetting('agui.workflow.conversation-2', '{not-valid-json');
|
||||
const store = new WorkflowCheckpointStore(adapter);
|
||||
|
||||
const loaded = await store.load('conversation-2');
|
||||
|
||||
expect(loaded).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null when stored checkpoint conversation id does not match', async () => {
|
||||
const adapter = new InMemorySettingsAdapter();
|
||||
await adapter.setSetting(
|
||||
'agui.workflow.conversation-3',
|
||||
JSON.stringify({
|
||||
conversationId: 'other-conversation',
|
||||
state: 'planning',
|
||||
pendingFields: [],
|
||||
lastTraceId: 'trace-mismatch',
|
||||
updatedAt: new Date('2026-02-25T10:00:00.000Z').toISOString(),
|
||||
}),
|
||||
);
|
||||
|
||||
const store = new WorkflowCheckpointStore(adapter);
|
||||
const loaded = await store.load('conversation-3');
|
||||
|
||||
expect(loaded).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,4 +35,72 @@ describe('AgentTurnStateMachine', () => {
|
||||
|
||||
expect(next).toBe('completed');
|
||||
});
|
||||
|
||||
it('transitions to executing when intent requests action execution', () => {
|
||||
const stateMachine = new AgentTurnStateMachine();
|
||||
|
||||
const next = stateMachine.transition({
|
||||
previousState: 'planning',
|
||||
envelope: {
|
||||
intent: 'execute_action',
|
||||
needsInput: {
|
||||
required: false,
|
||||
fields: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(next).toBe('executing');
|
||||
});
|
||||
|
||||
it('transitions to observing when proposing actions', () => {
|
||||
const stateMachine = new AgentTurnStateMachine();
|
||||
|
||||
const next = stateMachine.transition({
|
||||
previousState: 'planning',
|
||||
envelope: {
|
||||
intent: 'propose_action',
|
||||
needsInput: {
|
||||
required: false,
|
||||
fields: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(next).toBe('observing');
|
||||
});
|
||||
|
||||
it('returns to executing after awaiting input when input is no longer required', () => {
|
||||
const stateMachine = new AgentTurnStateMachine();
|
||||
|
||||
const next = stateMachine.transition({
|
||||
previousState: 'awaiting_input',
|
||||
envelope: {
|
||||
intent: 'analyze',
|
||||
needsInput: {
|
||||
required: false,
|
||||
fields: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(next).toBe('executing');
|
||||
});
|
||||
|
||||
it('stays in planning for non-terminal analyze intent by default', () => {
|
||||
const stateMachine = new AgentTurnStateMachine();
|
||||
|
||||
const next = stateMachine.transition({
|
||||
previousState: 'planning',
|
||||
envelope: {
|
||||
intent: 'analyze',
|
||||
needsInput: {
|
||||
required: false,
|
||||
fields: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(next).toBe('planning');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user