Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/agent-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,15 @@ export class AgentRuntime {
return stepEndData;
}

/**
* User-friendly alias for emitStepEnd().
*
* Keeps step lifecycle naming symmetric with beginStep().
*/
endStep(opts: Parameters<AgentRuntime['emitStepEnd']>[0] = {}): any {
return this.emitStepEnd(opts);
}

private async captureArtifactFrame(): Promise<void> {
if (!this.artifactBuffer) {
return;
Expand Down
11 changes: 10 additions & 1 deletion src/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { Tracer } from './tracing/tracer';
export class SentienceDebugger {
readonly runtime: AgentRuntime;
private stepOpen: boolean = false;
private autoStep: boolean = true;

constructor(runtime: AgentRuntime) {
constructor(runtime: AgentRuntime, options?: { autoStep?: boolean }) {
this.runtime = runtime;
this.autoStep = options?.autoStep !== undefined ? Boolean(options.autoStep) : true;
}

static attach(page: Page, tracer: Tracer, options?: AttachOptions): SentienceDebugger {
Expand Down Expand Up @@ -43,6 +45,13 @@ export class SentienceDebugger {

check(predicate: Predicate, label: string, required: boolean = false) {
if (!this.stepOpen) {
if (!this.autoStep) {
throw new Error(
`No active step. Call dbg.beginStep(...) or dbg.step(...) before check(label=${JSON.stringify(
label
)}).`
);
}
this.beginStep(`verify:${label}`);
}
return this.runtime.check(predicate, label, required);
Expand Down
12 changes: 12 additions & 0 deletions tests/agent-runtime-attach.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,15 @@ describe('AgentRuntime.fromPlaywrightPage()', () => {
spy.mockRestore();
});
});

describe('AgentRuntime.endStep()', () => {
it('aliases emitStepEnd()', () => {
const runtime: any = {
emitStepEnd: jest.fn().mockReturnValue({ ok: true }),
};

const out = (AgentRuntime.prototype as any).endStep.call(runtime, { action: 'noop' });
expect(runtime.emitStepEnd).toHaveBeenCalledWith({ action: 'noop' });
expect(out).toEqual({ ok: true });
});
});
13 changes: 13 additions & 0 deletions tests/debugger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,17 @@ describe('SentienceDebugger', () => {
expect(runtime.check).toHaveBeenCalled();
expect(handle).toBe('handle');
});

it('can disable auto-step (strict mode)', () => {
const runtime = {
beginStep: jest.fn().mockReturnValue('step-1'),
check: jest.fn().mockReturnValue('handle'),
} as unknown as AgentRuntime;

const dbg = new SentienceDebugger(runtime, { autoStep: false } as any);

expect(() =>
dbg.check((_ctx: any) => ({ passed: true, reason: '', details: {} }), 'has_cart')
).toThrow(/No active step/i);
});
});
Loading